Jekyll: How to include specific file from collection? - jekyll

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!

Related

Jekyll Internal Post Links

This is a pretty niche problem, but... I run a blog that runs on Jekyll and I post very regularly. To keep my editing sane I regularly archive posts, and those archived posts get a pretty strict structure. But, I go a full year before archiving.
Where this hurts is in links to other posts. I used to be able to absolutely reference the file name (per jekyll markdown internal links), but this appears to be being deprecated:
Deprecation: A call to '{% post_url 2018-09-06-peppermint %}' did not match a post using the new matching method of checking name (path-date-slug) equality. Please make sure that you change this tag to match the post's name exactly.
Now, if I have to include the full path to the file, then when I archive my posts for the year I have to parse all of the posts for the entire year and update any links between them to include the new file path for their archived location, defeating the point of using this tool at all. A direct link to the page would actually be better, given that I change my URL structure less often.
Is there a better solution for internal links that doesn't depend on the file structure, allowing a file to be moved without having to update every link to that file?
Example File structure:
_posts
-2018
-post1
-post2
-etc
-Archive
-2017
-2016
If there's no better answer, I may just have to go back to using absolute external links.
Solution 1. Use your own include
Create an post_url.html file and write this:
{% include post_url.html slug="2018-09-06-peppermint" %}
The include (called post_url.html) should find the post with the right slug and echo the link, like this:
{% assign link = site.posts | where:'slug',include.slug %}
{{ link[0].title }}
Solution 2. Search and replace
You have to parse posts? A simple search and replace on all files, looking for (/2018/ and replace with (/Archive/2018/ should do the trick (if you use markdown links). This should take just a few seconds.

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.

Is it possible in gh-pages Jekyll to have {{content}} expand without evaluating liquid tags?

I'm trying to use GitHub Pages for my project's documentation, but it includes generated html files that turn out to have illegal liquid tags. I don't need any expansion beyond the _layout itself, but as far as I can tell, any {% ... %} tags in the articles' content themselves are also evaluated and there seems to be no way to suppress this, other than adding {% raw %}...{% endraw %} around the entire contents of every single article.
Is there any way to do this at the call site? Something along the lines of {{ content | unrendered }} would be excellent.
Note: this seems to be the opposite problem to many others, who are using page.content in a pre-render context and wanting it to be rendered; I've tried page.content but as far as I can tell it's exactly the same in my case, so no dice.
page.content was raw in the jekyll 2.x era. Now its rendered content.
You can use a hook plugin to add a page.raw field on any page.
Jekyll::Hooks.register :pages, :pre_render do |document|
document.data['raw'] = document.content
end
If you want to do the same on posts and collections items, use a documents hook :
Jekyll::Hooks.register :documents, :pre_render do |document|
Note :
In :pre_render hooks document.content contains raw content
In :post_render hooks document.content contains rendered content

How to tune layout for a particular page/post in 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.

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.