Nested Jekyll liquid objects to pull _data file by today's date - jekyll

I have a Jekyll site with a _data directory full of files organized by date:
/_data/
mydata_2020-08-28.json
mydata_2020-08-29.json
mydata_2020-08-30.json
mydata_2020-08-31.json
I'd like to pull data from these files based on today's date, but I can't quite seem to get it right.
Let's say that I want to pull data from {{ site.data.mydata_2020-08-31.somefield }}, but I want to dynamically generate the date (YYYY-MM-DD) as today's date using {{ 'now' | date: "%Y-%m-%d" }}. I need to insert the date object into the data file object, but I can't find a way to do it.
I've tried:
{{ site.data.mydata_{{ 'now' | date: "%Y-%m-%d" }}.somefield }}
but it returns the truncated end of my liquid object:
.somefield
And I tried:
{{site.data.mydata_| append: 'now' | date: "%Y-%m-%d" | append:.somefield}}
which returns today's date:
2020-08-31
I also read through most of the documentation at https://shopify.github.io/liquid/, but maybe I'm overlooking something?

If you want to fetch data based on the date in your case, try with the following:
{% assign today_data = 'now' | date: "%Y-%m-%d" | prepend: 'mydata_' %}
# You can fetch data file with particular date as follows:
{{ site.data[today_data] }}
NOTE: .somefield can't be fetched in above approach.

Related

How to change month number in month name in Carbon Laravel 5.4

I have a table with a period and sales column.
the period look like this
2017001
2017002
......
2017011
2017012
I use the Carbon extension to extract the month number into month name with
{{ Carbon\Carbon::parse(substr($saleCurrent->period, -2))->month }}
but i'm getting an error
DateTime::__construct(): Failed to parse time string (01) at position 0 (0): Unexpected character
This is because the month should be 1 not 01 ?
Use the CreateFromFormat method so that you can pass in the format your dates are stored in:
{{ Carbon\Carbon::createFromFormat('Ymd', $saleCurrent->period)->month }}

Why converting to JSON a hash I initialized yield a null?

I am trying to build a hash in order to later output is as JSON (and ultimately import it to be reused by a a script). This is part of my static site built with jekyll.
Following the documentation on Expressions and Variables, I created a file with
---
---
{% assign aaa['bbb'] = 'xxx' %}
{{ aaa | jsonify }}
This was compiled by jekyll to a null (as if the hash was not initialized). Why is it so?
Sadly the documentation is talking about reading hash or arrays, not writing.
The only thing you can write from liquid is arrays.
create an empty array : {% assign my-array = "" | split: "/" %}{{
y-array | inspect }}
store with push or shift {% assign my-array = my-array | push: anything %}
= empty-array }}, where anything can be a string, an integer, a hash or an array.

How to filter a list by date condition?

I am trying to filter my list by looking for all items that have an end date less than or equal to today's date.
I know that in Liquid I can filter using where: to find items that match a condition. For example, if I wanted to get a list of today's conferences I could do:
{% assign todays_conferences = (site.conferences | where: 'date_end', today) %}
However, I can't do the same when I try to get upcoming conferences:
{% assign upcoming_conferences = (site.conferences | where: 'date_end', ??? | sort: 'date_start') %}
This is because I'm not looking to match a value one-to-one, but I'm trying to find items based on a date comparison. I have searched all over and unable to find a way.
How can I filter a list this way? I am hoping I wouldn't have to resort to looping through sequentially and doing an if statement on each row.
From Jekyll 3.2, Instead of using where you can use where_exp and filter the array with the objects where that expression is true:
{% assign upcoming_conferences = (site.conferences | where_exp: 'date_end', 'date_end < site.time' | sort: 'date_start') %}
You may replace site.time with any other valid date.

Using DateTime and DateInterval functions in Twig

I have two objects in Twig:
{{ date }} is DateTime object
{{ interval }} is DateInterval object
I need to show date with interval added. How can I use DateObject php function like add() with this two objects?
I can't do this on controller side, I need interval to date in twig. :(
You can use date_modify.
In your case, it would go as:
{{ yourDate|date_modify(yourInterval)|date("m/d/Y") }}

Liquid: Can I get a random element from an Array?

I'm trying to pick a random element from an array -- is this possible using Liquid/Jekyll?
I can create an array -- and access a given index ... but is there a way to "shuffle" the array and then select an index, and thus get a random element from the array?
prefix: ["Foo", "Bar", "Baz"]
---
{{ page.prefix[1] }}
# outputs "Bar"
The 2018 answer is
{% assign prefix = page.prefix | sample: 2 %}
{{ prefix[0] }}
As the OP asked about Jekyll, this can be found at: https://jekyllrb.com/docs/templates/
Liquid doesn't have a filter for picking a random element from an array or an integer interval.
If you want Jekyll to do that, you would have to create an extension to add that liquid filter.
However, I must point out that doing so would pick a random element every time the page is generated, but not every time the page is viewed.
If you want to get different random values every time you visit a page, your best option is using javascript and letting the client pick a random value. You can use liquid to generate the relevant javascript though.
You may be able to do that just in Liquid, but it could less of generic solution like the one provided by #Brendan. According to this article, you can generate a random liquid number between min & max. So simply:
Assign the min to 0 and max to your array's length.
Loop over the array till you find your random number and pick you element.
Here is an example, get your random array index:
{% assign min = 0 %}
{% assign max = prefix.size %}
{% assign diff = max | minus: min %}
{% assign randomNumber = "now" | date: "%N" | modulo: diff | plus: min %}
Then find your random value:
{{ prefix[randomNumber] }}
You can create a plugin to get a random element. Something like this:
module Jekyll
module RandomFilter
# Use sample to get a random value from an array
#
# input - The Array to sample.
#
# Examples
#
# random([1, 2, 3, 4, 5])
# # => ([2])
#
# Returns a randomly-selected item out of an array.
def random(input)
input.sample(1)
end
end
end
Liquid::Template.register_filter(Jekyll::RandomFilter)
Then do something like this in your template to implement:
{% assign myArray = '1|2|3|4|5 | split: '|' %}
{% assign myNumber = myArray | random %}
Without using a plugin (which might be a requirement if you are using github pages for example) and don't want the choice to be set only at build/rebuild time.
This uses collections as it's data source and some feature flags set in the page front matter.
{% if page.announcements %}
<script>
// homepage callout
var taglines=[
{% for txt in site.announcements %}
{{ txt.content | markdownify | jsonify | append: "," }}
{% endfor %}
]
var selection = document.querySelector('#tagline') !== null;
if(selection) {
document.querySelector('#tagline').innerHTML = taglines[ Math.floor(Math.random()*taglines.length) ];
}
</script>
{% endif %}
I use markdownify to process the content, jsonify to make it JavaScript safe and then append a comma to make my array.
The Javascript then populates one randomly at page load.
Add collection to config.yml
collections:
announcements:
Add flag to page
---
layout: home
title:
slider: true
announcements: true
---
collection content item (test.md)
---
published: true
---
This is a test post
You could adapt Liquid::Drop and whitelist Ruby's sample method.
See https://github.com/Shopify/liquid/blob/master/lib/liquid/drop.rb#L69:
You would need to change:
blacklist -= [:sort, :count, :first, :min, :max, :include?]
to:
blacklist -= [:sort, :count, :first, :min, :max, :include?, :sample]
Next you could just use:
{{ some_liquid_array.sample }}