I have an RSS template in Jekyll as below:
---
layout: nil
---
<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
<title>{{ site.title }}</title>
<link href="{{ site.url }}/feed.atom" rel="self"/>
<link href="{{ site.url }}/"/>
<updated>{{ site.time | date_to_xmlschema }}</updated>
<id>{{ site.url }}/</id>
<author>
<name>{{ site.author.name }}</name>
<email>{{ site.author.email }}</email>
</author>
{% for post in site.posts limit:20 %}
<entry>
<title>{{ post.title }}</title>
<link href="{{ site.url }}{{ post.url }}"/>
<updated>{{ post.date | date_to_xmlschema }}</updated>
<id>{{ site.url }}{{ post.id }}</id>
<content type="html">{{ post.content | replace:'src="/assets','src="http://example.com/assets' | xml_escape }}</content>
</entry>
{% endfor %}
</feed>
Now, I want http://example.com (currently hard-coded) to be replaced with {{ site.url }} variable. I have tried numerous ways, but am unable to achieve it.
Part of the answer was in the question :
{{ post.content | replace:'src="/assets','src="http://example.com/assets' | xml_escape | replace: 'http://example.com', site.url }}
Related
I've solved the error message
"Build Warning: Layout 'none' requested in feed.xml does not exist."
Removing three lines at the head of current feed.xml file. Is good solution? Whats wrong to remove these three lines?
---
layout: none
---
<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
<channel>
<title>{{ site.title | xml_escape }}</title>
<description>{{ site.description | xml_escape }}</description>
<link>{{ site.url }}{{ site.baseurl }}/</link>
<atom:link href="{{ "/feed.xml" | prepend: site.baseurl | prepend: site.url }}" rel="self" type="application/rss+xml" />
<pubDate>{{ site.time | date_to_rfc822 }}</pubDate>
<lastBuildDate>{{ site.time | date_to_rfc822 }}</lastBuildDate>
<generator>Jekyll v{{ jekyll.version }}</generator>
{% for post in site.posts limit:10 %}
<item>
<title>{{ post.title | xml_escape }}</title>
<description>{{ post.content | xml_escape }}</description>
<pubDate>{{ post.date | date_to_rfc822 }}</pubDate>
<link>{{ post.url | prepend: site.baseurl | prepend: site.url }}</link>
<guid isPermaLink="true">{{ post.url | prepend: site.baseurl | prepend: site.url }}</guid>
{% for tag in post.tags %}
<category>{{ tag | xml_escape }}</category>
{% endfor %}
{% for cat in post.categories %}
<category>{{ cat | xml_escape }}</category>
{% endfor %}
</item>
{% endfor %}
</channel>
</rss>
The correct expression is :
---
layout: null
---
I am trying to generate a post category-specific RSS feed for a GitHub Pages Jekyll website.
I understand that the jekyll-feed plugin can generate an RSS feed for all posts, but according to this GitHub Issue, category-specific feeds are not yet supported.
Other approaches to generate a category-specific feed (i.e., here and here are not supported by GitHub Pages because it won't support custom plugins.
Is there a way to generate a category-specific RSS feed using Jekyll with GitHub Pages?
You can just create your own XML or RSS file. For this answer I have used this example to build on. I also used Wikipedia for an example RSS feed.
filename: categoryname.rss
---
layout: null
---
<?xml version="1.0" encoding="UTF-8" ?>
<rss version="2.0">
<channel>
<title>{{ site.title }}</title>
<description>{{ site.description }}</description>
<link>{{ site.url }}</link>
<lastBuildDate>{{ site.time | date_to_rfc822 }}</lastBuildDate>
<pubDate>{{ site.time | date_to_rfc822 }}</pubDate>
<ttl>1800</ttl>
{% for post in site.categories.categoryname %}
<item>
<title>{{ post.title }}</title>
<description>{{ post.description }}</description>
<link>{{ post.url }}</link>
<guid isPermaLink="true">{{ site.url }}{{ post.url }}</guid>
<pubDate>{{ post.date | date_to_rfc822 }}</pubDate>
</item>
{% endfor %}
</channel>
</rss>
The title should be something like: 'mysitenames categoryname archive'. The description could be your category description. Link is the link to the category. The 'lastBuildDate' value could be the date of your last post and 'pubDate' could be the same.
Please let me know if you have any questions.
Following I've published for collections hosted on GitHub Pages, however, with modification it might by useful for categories too.
Downloading within another project is facilitated via Git's submodule features...
cd your-project
git checkout gh-pages
mkdir -vp _layouts/modules
git submodule add -b master --name feed-rss2\
https://github.com/liquid-utilities/feed-rss2.git\
_layouts/modules/feed-rss2
Note, https URLs are required for GitHub Pages compatibility.
... which should cause code similar to the following to become available...
_layouts/modules/feed-rss2/feed-rss2.html
---
layout: null
version: 0.0.1
license: AGPL-3.0
author: S0AndS0
---
{% capture workspace__rss2 %}
{% assign date_format = '%a, %d %b %Y %T %z' %}
{% assign collection_name = page.collection_name | default: include.collection_name | default: nil %}
{% assign target_collection = site[collection_name] %}
{% assign collection_home = page.collection_home | default: collection_name %}
{% assign collection_description = page.description | default: site.description %}
{% assign this_time_stamp = page.date | date: '%s' %}
{% assign latest_time_stamp = page.date | date: '%s' %}
{% assign rss_items_has_output = false %}
{% capture workspace__rss2__entries %}
{% for post in target_collection %}
{% if page.relative_path == post.relative_path or post.slug == 'feed' %}
{% continue %}
{% elsif post.slug == collection_name or post.slug == 'index' %}
{% continue %}
{% endif %}
{% assign rss_items_has_output = true %}
{% assign post_synopsis = post.description | default: post.excerpt %}
{% assign post_date_updated = post.date_updated | default: post.date %}
{% assign this_time_stamp = post_date_updated | date: '%s' %}
{% if latest_time_stamp < this_time_stamp %}{% comment %}> Syntax highlighting work-around{% endcomment %}
{% assign latest_time_stamp = this_time_stamp %}
{% endif %}
<item>
<title>{{- post.title | xml_escape -}}</title>
<link>{{- post.url | absolute_url -}}</link>
<guid isPermaLink="true">{{- post.url | absolute_url -}}</guid>
<pubDate>{{- post_date_updated | date: date_format -}}</pubDate>
<description>{{- post_synopsis | xml_escape -}}</description>
</item>
{% assign post_synopsis = nil %}
{% endfor %}
{% endcapture %}
{% assign page_rights = page.copyright | default: collection_home.copyright | default: site.copyright %}
{% assign page_rights = page_rights | default: site.github.license.name | default: 'All rights reserved' %}
<?xml version="1.0" encoding="UTF-8" ?>
<rss version="2.0">
<channel>
<title>{{- page.title | default: 'RSS Title' | xml_escape -}}</title>
<link>{{- page.url | absolute_url -}}</link>
<description>{{ collection_description | xml_escape }}</description>
<copyright>Copyright {{ site.time | date: '%Y' }} {{ page_author | xml_escape }}. {{ page_rights | xml_escape }}</copyright>
<lastBuildDate>{{- site.time | date: date_format -}}</lastBuildDate>
<pubDate>{{- latest_time_stamp | date: date_format -}}</pubDate>
<ttl>{{- page.time_to_live | default: '1800' -}}</ttl>
{% if rss_items_has_output %}
{{ workspace__rss2__entries | strip }}{% assign workspace__rss2__entries = nil %}
{% endif %}
</channel>
</rss>
{% endcapture %}{{ workspace__rss2 | strip }}{% assign workspace__rss2 = nil %}
... Setting a feed file within a collection directory would then look like...
_example-collection/example-collection.rss
---
layout: modules/feed-rss2/feed-rss2
title: Example Collection
collection_name: example-collection
collection_home: /example-collection/
date: 2019-07-23 21:12:13 -0700
content_type: xhtml
permalink: /:collection/:name:output_ext
---
... and minor additions of FrontMatter of each post/page...
_example-collection/something-about-something.markdown
---
layout: post
title: Something About Something
description: Example collection page about something
date: 2019-07-21 11:42:11 -0300
time_to_live: 1800
---
... Which should render results similar to the live demo hosted by GitHub Pages.
Note, check the documentation for updating and cloning tips and caveats.
Regardless of if ya utilize the above project's code I'll suggest looking into the submodule features (hint git help submodule), because such things allow for code reuse in multiple repositories while keeping things version tracked and easily updated. Plus submodules are compatible with GitHub Pages, meaning that submodules are about as close to third-party plugin support as one can get without exploring Continuous Integration solutions.
The other key take-away would be, to try and utilize layouts for these types of solutions.
Feel free to comment if ya get stuck or something from above is confusing.
Expanding on JoostS answer:
---
layout: null
---
<?xml version="1.0" encoding="UTF-8" ?>
<rss version="2.0">
<channel>
<title>{{ site.title }}</title>
<description>{{ site.description }}</description>
<link>{{ site.url }}</link>
<lastBuildDate>{{ site.time | date_to_rfc822 }}</lastBuildDate>
<pubDate>{{ site.time | date_to_rfc822 }}</pubDate>
<ttl>1800</ttl>
{% for post in site.pages %}
{% if post.title %}
<item>
<title>{{ post.title }}</title>
<description>{{ post.description }}</description>
<link>{{ site.url }}{{ post.url }}</link>
<guid isPermaLink="true">{{ site.url }}{{ post.url }}</guid>
<pubDate>{{ post.date | date_to_rfc822 }}</pubDate>
</item>
{% endif %}
{% endfor %}
</channel>
</rss>
I was wondering if there is a more efficient way to create hreflang tags, just using liquid in BC, without the need to create webapp.
I tried this way which makes sense, but it doesn't work for some reason.
{% capture pagURL -%}{module_pageaddress}{% endcapture -%}
{% if pagURL contains "http://us." -%}
<link rel="alternate" href="{{ pagURL}}" hreflang="en-us" />
<link rel="alternate" href="{{ pagURL | replace: 'http://us', 'http://www' }}" hreflang="en-uk" />
<link rel="alternate" href="{{ pagURL | replace: 'http://us', 'http://au' }}" hreflang="en-au" />
<link rel="alternate" href="{{ pagURL | replace: 'http://us', 'http://eu' }}" hreflang="en" />
{% elsif pagURL contains "http://au." -%}
<link rel="alternate" href="{{ pagURL}}" hreflang="en-au" />
<link rel="alternate" href="{{ pagURL | replace: 'http://au', 'http://www' }}" hreflang="en-uk" />
<link rel="alternate" href="{{ pagURL | replace: 'http://au', 'http://us' }}" hreflang="en-us" />
<link rel="alternate" href="{{ pagURL | replace: 'http://au', 'http://eu' }}" hreflang="en" />
{% elsif pagURL contains "http://eu." -%}
<link rel="alternate" href="{{ pagURL}}" hreflang="en" />
<link rel="alternate" href="{{ pagURL | replace: 'http://eu', 'http://us' }}" hreflang="en-us" />
<link rel="alternate" href="{{ pagURL | replace: 'http://eu', 'http://au' }}" hreflang="en-au" />
<link rel="alternate" href="{{ pagURL | replace: 'http://eu', 'http://www' }}" hreflang="en-uk" />
{% elseif pagURL contains "http://www." -%}
<link rel="alternate" href="{{ pagURL}}" hreflang="en-uk" />
<link rel="alternate" href="{{ pagURL | replace: 'http://www', 'http://us' }}" hreflang="en-us" />
<link rel="alternate" href="{{ pagURL | replace: 'http://www', 'http://au' }}" hreflang="en-au" />
<link rel="alternate" href="{{ pagURL | replace: 'http://www', 'http://eu' }}" hreflang="en" />
{% else -%}
{% endif -%}
The weird part is, the following it works on that same page.
{% capture pagURL -%}{module_pageaddress}{% endcapture -%}
{{ pagURL}}<br>
{{ pagURL | replace: 'http://www', 'http://us' }}<br>
{{ pagURL | replace: 'http://www', 'http://au' }}<br>
{{ pagURL | replace: 'http://www', 'http://eu' }}<br>
And this also works
{{ pagURL | replace: 'http://www', 'http://us' | prepend: '<link rel="alternate" href="' | append: '" hreflang="en-us" />' }}
The shorter the code the better of course.
Ok Daut, you're going to love this! ;p
I ran into similar obstacles when working on a solution for this issue. (I'll explain below).
As far as I can tell, BC has some issues around its rendering of Liquid when it comes to URLs and variables. I don't really understand the ins and outs of Liquid in terms of the server-side processing but things do not appear to work as they should in BC.
For example, if we take your code and strip it back to its bare essentials:
This (whether inserted into the <head> or <body>) DOESN'T work:
{% capture pagURL -%}
{module_pageaddress}
{% endcapture -%}
<link rel="alternate" href="{{pagURL}}" hreflang="en-us">
It outputs <link rel="alternate" href="{{pagURL}}" hreflang="en-us">, {{pagURL}} being the literal text that is rendered.
But this DOES work:
{% capture pagURL -%}
{module_pageaddress}
{% endcapture -%}
{% assign test = '<link rel="alternate" href="' | append: {{pagURL}} | append: '" hreflang="en-us">' -%}
{{test}}
Compare the above to the issues I ran into.
This DOESN'T work:
{module_pageaddress collection="page" template=""}
{module_siteUrl collection="site" template=""}
{% assign fullUrl = "http://{{site.siteUrl}}/" -%}
{% if page.pageUrl == {{fullUrl}} -%}
// We are on the home page
{% else -%}
// We are not on the home page
{% endif -%}
The problem here is {{site.siteUrl}} inside the variable declaration. Not sure what the issue is but it just can't handle the jandle.
But this DOES work:
{module_pageaddress collection="page" template=""}
{module_siteUrl collection="site" template=""}
{% assign fullUrl = 'http://' | append: {{site.siteUrl}} | append: '/' -%}
{% if page.pageUrl == {{fullUrl}} -%}
// We are on the home page
{% else -%}
// We are not on the home page
{% endif -%}
And finally getting back to your example, (ironically) this works:
{% capture pagURL -%}
{module_pageaddress}
{% endcapture -%}
test
Go figure.
I'm pretty sure that BC has some automatic way of grabbing head elements contained anywhere on a page and re-inserting them into the head (even if they were inserted into the head to begin with).
I wonder if that causes problems in cases like <link rel="alternate" href="{{pagURL}}" hreflang="en-us">. It doesn't explain the issue I ran into though.
End of the day, I think there are still some big issues with BC's implementation of Liquid.
I've recently converted my blog to Jekyll environment, then I added the following particular feed which used by few site aggregators. However, I noticed that images are not being incorporated in the aggregators, for instance here.
As I write the posts in markdown, I thought it could be some confusing image path, so I changed the path of couple posts from ![](/images/blog/2015/GoogleNgram.png) to: ![]({{ site.url }}/images/blog/2015/GoogleNgram.png) but nothing happened. Any advice will be highly appreciated.
---
layout: null
---
<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
<channel>
<title>Daniel</title>
<description>Posts categorized as 'R'</description>
<link>{{ site.url }}</link>
<atom:link href="{{ site.url }}/feed.r.xml" rel="self" type="application/rss+xml" />
{% for post in site.posts %}
{% if post.categories contains 'R' %}
<item>
<title>{{ post.title | xml_escape }}</title>
{% if post.excerpt %}
<description>{{ post.excerpt | xml_escape }}</description>
{% else %}
<description>{{ post.content | xml_escape }}</description>
{% endif %}
<pubDate>{{ post.date | date_to_rfc822 }}</pubDate>
<link>{{ site.url }}{{ post.url }}</link>
<guid isPermaLink="true">{{ site.url }}{{ post.url }}</guid>
</item>
{% endif %}
{% endfor %}
</channel>
</rss>
In my index of blog posts I'd like to grab the first image from the post to display it in the index using just liquid so it works on github pages.
I have a feeling split is the way to go, but I'm not good with liquid.
I'd like to be able to get the image url and put it in a variable to style it.
The ideal solution would be something like:
{% for post in site.posts %}
<li>
{{post.content | first_image}}
</li>
{% endfor %}
Any ideas?
You can define a custom variable to your Front Matter called "image", so it's going to work like Wordpress's posts Featured Image:
---
image: featured-image.jpg
---
Note to remember where is your image saved. In my case, I created a directory called "imagens" (PT-BR here). Then, go to your index.html and add the image to your template, wherever you want. In my site it looks like this:
<ul class="post-list">
{% for post in site.posts %}
<li>
<h2>
<a class="post-link" href="{{ post.url | prepend: site.baseurl }}">{{ post.title }}</a>
</h2>
<span class="post-meta">{{ post.date | date: "%b %-d, %Y" }},</span>
<span class="post-meta">por</span>
<span class="post-meta">{{ post.author }}</span>
</li>
//IMAGE
<img src="{{ site.baseurl }}/imagens/{{ post.image }}">
//IMAGE
{{ post.excerpt }}
<a class="btn btn-default" href="{{ post.url | prepend: site.baseurl }}">Continuar lendo</a>
{% endfor %}
</ul>
That's it.
Some solutions to your problem :
1 - Use the Post Excerpt tag Documentation is here
Your post :
---
layout: post
title: Testing images
---
## Title
Intro Text
![Image alt]({{ site.baseurl }}/assets/img/image.jpg "image title")
More intro text
Some more text blah !
Your template :
<ul>
{% for post in site.posts %}
<li>
{{ post.title }}
{{ post.excerpt }}
</li>
{% endfor %}
</ul>
As your image tag appears before the excerpt_separator (\n\n = two newlines) it will be in the post excerpt.
2 - Use your post's Yaml front matter to store your image's datas
Post :
---
layout: post
title: Testing images
images:
- url: /assets/img/cypripedium-calceolum.jpg
alt: Cypripedium Calceolum
title: Cypripedium Calceolum
- url: /assets/img/hello-bumblebee.jpg
alt: Hello bumblebee !
title: Hello bumblebee !
---
Intro here yo ! <-- THIS IS THE EXCERPT
Post body begin, and first image not in excerpt
{% assign image = page.images[0] %} <-- first element of the array is zero
{% include image.html image=image %}
Some more text blah !
{% assign image = page.images[1] %}
{% include image.html image=image %}
_includes/image.html (centralized in an include for standardization, but can be in the template) :
<img src="{{ site.baseurl }}{{ include.image.url }}" alt="{{ include.image.alt }}" title="{{ include.image.title }}">
The index page :
<ul class="posts">
{% for post in site.posts %}
<li>
<span class="post-date">{{ post.date | date: "%b %-d, %Y" }}</span>
<a class="post-link" href="{{ post.url | prepend: site.baseurl }}">{{ post.title }}</a>
{{ post.excerpt }}
{% assign image = post.images[0] %}
{% include image.html image=image %}
</li>
{% endfor %}
</ul>
Got it to work. Not sure how it will scale, but this liquid code loops through all the posts and grabs the source for the first image from a post and displays that post. I tested it with multiple images and it works as expected.
<ul>
{% for post in site.posts %}
<li>
{% assign foundImage = 0 %}
{% assign images = post.content | split:"<img " %}
{% for image in images %}
{% if image contains 'src' %}
{% if foundImage == 0 %}
{% assign html = image | split:"/>" | first %}
<img {{ html }} />
{% assign foundImage = 1 %}
{% endif %}
{% endif %}
{% endfor %}
{{ post.title }}
</li>
{% endfor %}
</ul>
If you just need the image URL instead of the whole thing in img tag, you can use the following method.
Install Liquid filter match_regex:
gem install match_regex
Then add it to your Jekyll config:
plugins:
- match_regex
Create a capture snippet in your template:
{% capture post_first_image %}
{% assign hero_image = page.content | match_regex: '<img .*?src="([^"]+)"' %}
{% if hero_image == nil %}
{% assign hero_image = "/placeholder-image.png" | prepend: site_base %}
{% endif %}
{{ hero_image }}
{% endcapture %}
Template:
<meta property="og:image" content="{{ post_first_image | strip }}">
You can simply remove the if condition if you don't need placeholder image.
I've taken David's answer and found a way to get just the src attribute from the img tag.
{% assign foundImage = 0 %}
{% assign images = post.content | split:"<img " %}
{% for image in images %}
{% if image contains 'src' %}
{% if foundImage == 0 %}
{% assign html = image | split:"/>" | first %}
{% assign tags = html | split:" " %}
{% for tag in tags %}
{% if tag contains 'src' %}
<img {{ tag }} />
{% endif %}
{% endfor %}
{% assign foundImage = 1 %}
{% endif %}
{% endif %}
{% endfor %}