How to tune layout for a particular page/post in Jekyll? - jekyll

I would like to make some changes in Jekyll's layout. Changes are small and different. For example, linking an additional CSS or JavaScript file. Or adding some info in header. Or tuning page title.
Important that these changes depend on a page/post.
Since changes are small and diverse, creating a special layout for each of them seems to be too expensive.
I tried to create my own solution but run into impossibility to use variables in including instructions.
Has anyone solved something similar? For example, linking a special CSS to a particular post?

You can use YAML front matter to tune anything you want for any post/page. Any info you provide there would be accessible through in layouts and includes under page variable or under specific post in any list of them.
This sounds like a solution for your case: you could use YAML front matter like this:
---
extra_css:
- foo.css
- dir/bar.css
- /s/baz.css
---
And then use this in your layout's header like this:
{% for css_name in page.extra_css %}
<link rel="stylesheet" href="{{ css_name }}">
{% endfor %}
In such way you could add any logic based on what data you provide with a post in YAML front matter.
If you'd like to abstract some of those logic to modules, you can use a hack around the includes, assigning a variable before that include and then using it inside. Here is a link with a description how it's made in Jekyll Bootstrap project (btw, the site for it have a lot of nice info on Jekyll).
And, yes, Jekyll don't allow the use of variables in includes, so if you'd like to include something conditionally, you would need a list of all available includes somewhere and then create all the conditions for inserting one or another when you'll need them.
Another solution is to divide everything in layout to includes, and make layouts with different levels of complexity — this way you could set any of those basic layouts for post and then write any extra code with includes of any blocks you'll need from the basic layouts, so you post could look like this:
---
layout: custom
---
<aside class="sidebar">
{% include comments.html %}
{% include sidebar.html %}
</aside>
<div class="content" role="main">
Foo bar baz
</div>
There you could use a custom layout that don't include a basic layout for page and don't include the sidebar and comments, so you could per-post decide what level of layout you want and then redefine anything that needed to be redefined.
Also, if you'll need to tweak different places but with an unknown content, you could use YAML front matter with blocks, like
extra_head: |
<style>
* {background: red}
</style>
then you could call such variable from head: {{ page.extra_head }} and get any content you placed there. However, you can't use any liquid tags inside YAML, but you could then use any YAML tags on such variables, so you could markdownify them or replace any strings inside with anything else by simple replace filter.
And if nothing of those fit you, then Jekyll won't fit you — as I wrote in a comment, Jekyll is just a blog engine and you shouldn't wait it to be complex as XSLT.

I have ever tried to create an independent page in the jekyll-bootstrap static site. For example my_cv.html which needs independent css style. Instead of create a new github repository with gh-pages (sorry GitHub), I just simply fill all the final html contents into the a post my_cv.md since markdown format is actually compatible with html I think, and luckily it works.

Related

Can I generate a references index/ book index from markdown to html (ideally in a static site)?

For an academic project, I would like to make an index. You know, that boring list of words that indicates in which pages every word listed is. This : https://www.pdfindexgenerator.com/what-is-a-book-index/. But for a website.
My goal is, let's say, from Markdown, to generate HTML pages. I would love to do this with a static site, because the content won't evolve every day, and it appears to me that I'd have to parse all the content anyway. Maybe the solution is just using a wiki.
Here's how I would have done it : you write a bunch of text into page.md, inside this text you identify a [word] that you want to see in your index with a specific markup. And then you mention this same [word] with the same markup into otherpage.md.
Then, the generator extracts all the marked words, makes a list, and generates a page with the links to all the references to each marked word.
Word:
page.html
otherpage.html
A reference index. Yay.
What I want is like a simpler version of LaTeX's MakeIndex. Like, closer to this https://wordpress.org/plugins/lexicographer/, but not for definitions, only for internal references.
Pandoc seems to not be supporting indices, maybe because MakeIndex is very complex (but indices are actually, so well, that's fair play) or just because it's made for page numbers and not html links.
So :
I know indices are actually complicated stuff. It's impossible to fully
automatize. My only goal here is to be able to tag the words as I
write and having some computer help to make the listing at the end and render a neat HTML page
with all the links because this part is really boring (like MakeIndex does). But maybe just this
part is impossible and I'd be fine with this.
Is this already implemented somewhere, if it's not impossible? There is plenty of static sites and wikis and stuff, maybe someone thought about it before me, as indices are academic stuff used for CENTURIES. Maybe there's a plugin or a piece of software I just don't know.
I would appreciate just pointers to know where to go to do this if its doable. There is a start here How to generate (book) indexes? but it's too little for me to understand what to do next.
Thanks a lot <3
Using Pelican you can use tags that way.
You can add the following to your index.html template to loop through existing tags :
{% if tags %}
{% for tag, articles in tags %}
{{tag }} :
<ul>
{%for article in articles%}
<li>{{ article.title }}</li>
{% endfor %}
</ul>
{% endfor %}
{% endif %}
Then you will get the following result :
You can't directly tag your text the way you showed though. You'll have to add the tag line in your article's headings :
Title: mytitle
Date: 2020-05-19
Tags: firsttag, othertag
...
You can add this to your index.html template or to tags.html, as you see fit.

How to create new entities in Jekyll + Markdown

I have a bunch of Markdown files. In them, I want to be able to use custom bullets and other images; these are implemented as images (with alt-text, but they're a lot prettier as images). The Markdown to create one of those images looks like this:
*![✨](https://s.w.org/images/core/emoji/2.2.1/svg/2728.svg)*
(Yes, that's rendered inside <em> </em> - that's to simplify the CSS, since I can't put a class on the img tag easily.)
Is there a way to tell the parser that the single character ✨ should be rendered as the entire <img> tag?
The site is hosted on GitHub Pages, so answers need to restrict themselves to GitHub Flavored Markdown. If it can't easily be done, I could make a pre-commit hook or something and run a local parser, but it would be far easier to have it work automatically.
You can put the emojis in includes and then reference them from your posts. That is compatible with Github Pages as it doesn't require plugins.
In your post put:
{% include emoji.html %}
That will load the contents of _includes/emoji.html:
✨
You can pass parameters to it to load different images depending on the image you want to load, e.g.: {% include emoji.html image="stars" %}
Another option is to create custom liquid tags that load them.
...since I can't put a class on the img tag easily.
You can if you use kramdown - it has a feature, which allows assigning attributes to the block level elements. For example:
![img]({{ 'img.png' | relative_url }}){: .center }
will become
<img src="...img.png" alt="img" class="center">

Jekyll: How to include specific file from collection?

I have a collection of css files I combine into one with Jekyll. This is very easy:
{% for file in site.css %}
{{ file }}
{% endfor %}
However, there is a special case where I want to include just a single one of those files. The pages.css file.
site.css is a collection, so I simply put all my css files in a folder called _css and in _config.yml added:
collections:
css:
output: false
I was able to include only the _css/pages.css files using {{ site.css | where:"title", "Pages" | first }}. But I was wondering if there is a nicer way of doing it. Something like {{ site.css/pages.css }}
Is there a way to do it like that? Wihtout a where and first clause?
For the exception I would use an if statement and not loop over the files.
However, I would consider cache while using this solution. If one pages uses 'superlargecombined.css' and another one uses 'superlargecombinedcsswithoutonepart.css' the client needs to download them both (fully). That is in not an optimization. If you keep your css files seperated they can be cached and will be downloaded once, independent of your page css configuration. Combining things that always need to stick together is a good solution though (to minimize requests), but note that with HTTP2 the need to minimize requests will reduce drastically.
Hope this helps!

How can I use macros/variables/scripts in articles with Pelican?

I have just started with Pelican. It's awesome, I just can't figure out how to use macros in my articles (and pages). I know I can use Jinja when making my own theme, but I can't seem to be able to use it in articles. I'd like to be able to define a macro/function/template/whatever that I'd put directly in the markdown of the article, possibly with parameters, and it would get expanded when the pages are generated. For example a function to generate an image with a caption of given size and css class that would also be a link directly to the image. I'd like to be able to access these macros from all articles, to be able to reuse them everywhere. Something I'd normally do with PhP.
I could probably use JS to do this, but if I'd like to avoid it and keep everything static if possible. Can this be done?
UPDATE:
I found a pelican plugin that solves this - jinja2content.
OLD SOLUTION:
I found a solution here. You can implement a filter in Python to process all texts in articles/pages like this:
Create a python file filters.py in which you write the filter function process_text to expand my macros (or generally do anything with the article/page text), for example to test the function write something like:
def process_text(input_text):
return "TEST " + input_text
In the Pelican config file (pelicanconfig.py) register this function as a possible filter to be used with Jinja:
import sys
sys.path.append('.')
import filters
JINJA_FILTERS = {'process_text':filters.process_text}
Now you have to edit the templates to apply this filter to article/page texts before adding them to output. In my case I edited two files: themes/themename/templates/article.html and themes/themename/templates/post.html and changed {{ article.content }} to {{ article.content|process_text }} and {{ page.content }} to {{ page.content|process_text }} in them to apply the filter.
Now all texts in articles and pages should be prefixed with "TEST".
The not so convenient thing about this is I have to write my own macro expander, which shouldn't be extremely hard with regular expression in Python, but if there is a nicer way to do this, feel free to post here.

How do I reuse HTML snippets in a django view

I am working on a django project (my first), and in one of my views, I have a sophisticated html snippet with JS weaved within it. I would like to reuse this "component" somewhere else in the same view. Is there a way of achieving this? Please let me know if this design is faulty to begin with?
Use the {% include '/my/common/template.html' %} templatetag.
Loads a template and renders it with
the current context. This is a way of
"including" other templates within a
template.
The template name can either be a
variable or a hard-coded (quoted)
string, in either single or double
quotes.
I know it's an old one but maybe someone is gonna have use of this answer.
There's also the inclusion tag. It's like the include tag, only you can pass it arguments and process it as a seperate template.
Put this in my_app/templatetags/my_templatetags.py:
#register.inclusion_tag('my_snippet.html')
def my_snippet(url, title):
return {'url': url, 'title': title}
and then my_snippet.html can be:
{{ title }}
then, to use this snippet in your templates:
{% load my_templatetags %}
{% my_snippet "/homepage/" "Homepage" %}
More info:
https://docs.djangoproject.com/en/dev/howto/custom-template-tags/#howto-custom-template-tags-inclusion-tags
Not sure, if you like to reuse your HTML in different templates (rendered by different views). If so, look into Django's template inheritance mechanism:
The most powerful -- and thus the most complex -- part of Django's template engine is template inheritance. Template inheritance allows you to build a base "skeleton" template that contains all the common elements of your site and defines blocks that child templates can override.
You should try Django custom template tags. This way you will keep your snippets in an external file and then call them easily by something like {{ your_custom_tag }}. It's a very convenient method for working with reusable chunks of xhtml markup. You can even use arguments with these custom tags, something like {{ your_custom_tag|image:"logo.png" }}.
You can learn more about custom tags here.