Skip to content

Latest commit

 

History

History
100 lines (70 loc) · 8.3 KB

File metadata and controls

100 lines (70 loc) · 8.3 KB
description
A generic and flexible way to automatically list large sets of items

List

👁️ PREVIEW

Takes a list of data, filters it, loops through it, and displays each item with some component.

{%
  include list.html
  data="citations"
  component="citation"
  filter="category == 'featured'"
  style="rich"
%}
ParameterDescription
dataThe set of items to loop through, e.g. citations, posts, members, etc. If your list has date fields, it is also sorted from newest to oldest, and grouped into sections by year.
componentThe component to show for each item in the list. The fields in your data should match what this component takes as parameters (except for style, see below).
filterFilter your data by arbitrary fields and values. See detailed explanation below.
styleA style parameter to automatically pass to every component in the list, so you don't have to repetitively set it on every data item. This is the only field that works this way, because all other fields are likely to be different for each item, but you usually want the style to be the same within a list.

Technically you can use any structure of data and any component with the list component, but by default, the template comes with a few placeholder data lists and matching components for common needs.

Filter

{% hint style="info" %} New syntax, v1.3.0+ {% endhint %}

The filter parameter offers a flexible way to filter the items displayed by the list component. It can be any valid Ruby expression. For each item, if the expression is true, the item is shown; otherwise, it is hidden.

Your expression can get/check any field on any item in any data list. Simply refer to a field by its name, but in snake_case format (anything not a letter replaced with a _). You can also get a field by its unmodified name from item (a hash). If the expression references something that isn't a field on the item, it will treat it as nil (null).

For example, if your data looked like this:

# ... previous item

# current item filter is looking at
- id: abc
  Some-Field-123: xxx

# ... another item
- id: def
  Some-Field-123: yyy
  optional-field: Lorem ipsum

...you could make references in your filter="" like this:

# snake_cased field name
Some_Field
# exact original field name
item['Some-Field-123']
# field perhaps present on other items, but not present on this item
optional_field # treated as `nil` (null)

Examples

Filter expressionShow item if...Example scenario
repohas some repo field"Show my tools that have a repo link"
!idhas no id field"Show my manual citations"
type == 'package' and category != 'featured'type is package and category is not featured"Show my secondary packages"
role =~ /student/irole contains student, case-insensitive"Show my students, of any level"
role =~ /^Senior/role starts with Senior, case-sensitive"Show my senior level members"
date.between?('2020', '2023')date is between 2020 and 2023 "Show my papers published during COVID"
publisher.end_with?('Biology')publisher ends with Biology"Show my papers in major biology journals"
alumni ? name === 'Steve McQueen' : truenot alumni , or alumni where name is Steve McQueen"Hide my past members, unless they're super cool"

{% hint style="info" %} References:

/Regex/

Ruby string functions {% endhint %}

Experiment with more advanced expressions:

{% embed url="https://try.ruby-lang.org/playground/#code=data+%3D+%5B%0A++%7B%22name%22+%3D%3E+%22Jane+Smith%22%2C+%22date%22+%3D%3E+%222015-01-01%22%7D%2C%0A++%7B%22name%22+%3D%3E+%22John+Smith%22%2C+%22date%22+%3D%3E+%222019-02-01%22%7D%2C%0A++%7B%22name%22+%3D%3E+%22Ada+Lovelace%22%2C+%22date%22+%3D%3E+%222020-03-01%22%2C+%22alumni%22%3D%3E+true%7D%2C%0A++%7B%22name%22+%3D%3E+%22Alan+Turing%22%2C+%22date%22+%3D%3E+%222024-04-01%22%2C+%22alumni%22%3D%3E+true%7D%2C%0A++%7B%22name%22+%3D%3E+%22Margaret+Hamilton%22%2C+%22date%22+%3D%3E+%222018-05-01%22%2C+%22alumni%22%3D%3E+true%7D%2C%0A%5D%0A%0Afilter+%3D+%22alumni+%3F+!name.start_with%3F('A')+%3A+true%22%0A%0A%0A%23%23%23%23%23%23%23%23%23%23%23%0A%0A%0Adef+empty_binding%0A++binding%0Aend%0A%0A%23+make+arbitrary+string+into+valid+ruby+variable+name%0Adef+safe_var_name(name)%0A++return+name.to_s.gsub(%2F%5B%5Ea-z%5D%2B%2Fi%2C+%22_%22).gsub(%2F%5E_%7C_%24%2F%2C+%22%22)%0Aend%0A%0A%23+filter+a+list+of+hashes%0Adef+data_filter(data%2C+filter)%0A++if+not+filter.is_a%3F(String)%0A++++return+data%0A++end%0A%0A++%23+filter+data%0A++return+data.clone.select%7B%0A++++%7Citem%7C%0A++++%23+start+with+empty+context+of+local+variables%0A++++b+%3D+empty_binding%0A++++%23+add+item+as+local+variable%0A++++b.local_variable_set(%22item%22%2C+item)%0A++++%23+also+set+each+item+field+as+local+variable+when+evaluating+filter%0A++++item.each+do+%7Cvar%2C+val%7C%0A++++++b.local_variable_set(safe_var_name(var)%2C+val)%0A++++end%0A++++%23+whether+to+keep+item%0A++++keep+%3D+true%0A++++while+true%0A++++++begin%0A++++++++%23+evaluate+expression+as+true%2Ffalse%0A++++++++keep+%3D+!!eval(filter%2C+b)%0A++++++++break%0A++++++++%23+if+a+var+in+expression+isn't+a+field+on+item%0A++++++rescue+NameError+%3D%3E+e%0A++++++++%23+define+it+and+re-evaluate%0A++++++++b.local_variable_set(safe_var_name(e.name)%2C+nil)%0A++++++end%0A++++end%0A++++%23+keep%2Fdiscard+item%0A++++keep%0A++%7D%0Aend%0A%0Afiltered+%3D+data_filter(data%2C+filter)%0A%0Afiltered.each+do+%7Citem%7C%0A++puts+item%0Aend&engine=cruby-3.2.0" %}

Filters

{% hint style="danger" %} Old syntax, < v1.3.0 {% endhint %}

The filters parameter is a comma separated list of field/value filters, like field: value, field: value, field: value. An item is considered a match only if all of the filters match.

The field is the particular field/key of the data item to check. The value is the value to compare against. value can be:

  • A plain string for a partial match.
  • Blank to match unspecified fields.
  • Ruby-flavored regex string for more complex matching.

Examples

Filter string Show items that have...
role: programmer, alumni: true role containing programmer AND alumni containing true
affiliation: ^CU$ affiliation EXACTLY equal to CU
category: no specified category
description: .+ some specified/defined description
date: ^2020 date starting with 2020
role: ^(?!pi$) role NOT equal to pi