diff --git a/_includes/button.html b/_includes/button.html
index 47ed98bd2e..11739b2db2 100644
--- a/_includes/button.html
+++ b/_includes/button.html
@@ -1,5 +1,4 @@
-{% assign button = include %}
-{% assign button = button | hash_default: site.data.types[include.type] %}
+{% assign button = include | hash_default: site.data.types[include.type] %}
{% if button.link or button.icon or button.text %}
diff --git a/_includes/list.html b/_includes/list.html
index cdb030c956..5dec46ed76 100644
--- a/_includes/list.html
+++ b/_includes/list.html
@@ -2,7 +2,7 @@
{% assign data = site.data[include.data]
| default: site[include.data]
| default: emptyarray
- | data_filter: include.filters
+ | data_filter: include.filter
%}
{% assign years = data
diff --git a/_plugins/hash.rb b/_plugins/hash.rb
index 23445898ab..7bf6071395 100644
--- a/_plugins/hash.rb
+++ b/_plugins/hash.rb
@@ -4,7 +4,7 @@ module Jekyll
module HashFilters
# merge main hash with another hash of defaults
def hash_default(hash, defaults)
- if not hash.is_a?(Hash) or not defaults.is_a?(Hash)
+ if not defaults.is_a?(Hash)
return hash
end
defaults.each do |key, value|
diff --git a/_plugins/misc.rb b/_plugins/misc.rb
index fe19bd8f08..a4186d1a74 100644
--- a/_plugins/misc.rb
+++ b/_plugins/misc.rb
@@ -19,22 +19,52 @@ def object_items(object)
end
# filter a list of hashes by comma-sep'd field:value pairs
- def data_filter(data, filters)
- if not data.is_a?(Array) or not filters.is_a?(String)
+ def empty_binding
+ binding
+ end
+
+ # make arbitrary string into valid ruby variable name
+ def safe_var_name(name)
+ return name.to_s.gsub /[^a-z]+/, "_"
+ end
+
+ # jekyll ruby plugin
+ def data_filter(data, filter)
+ if not filter.is_a?(String)
return data
end
- data = data.clone
- for filter in array_filter(filters.split(","))
- key, value = array_filter(filter.split(":"))
- # find unspecified fields
- if value == nil
- data.select!{|d| d[key] == nil}
- # find fields that match regex
- elsif value.is_a?(String)
- data.select!{|d| d[key].to_s =~ /#{value}/m}
+
+ # filter data
+ return data.clone.select{
+ |item|
+ # start with empty context of local variables
+ b = empty_binding
+ # add item as local variable
+ b.local_variable_set("item", item)
+ # if jekyll doc collection, get hash of doc data
+ if item.is_a? Jekyll::Document
+ item = item.data
end
- end
- return data
+ # also set each item field as local variable when evaluating filter
+ item.each do |var, val|
+ b.local_variable_set(safe_var_name(var), val)
+ end
+ # whether to keep item
+ keep = true
+ while true
+ begin
+ # evaluate filter code, coerce to true/false
+ keep = !!eval(filter, b)
+ # if no error, done
+ break
+ rescue NameError => e
+ # if var in filter doesn't exist, define it and re-evaluate
+ b.local_variable_set(safe_var_name(e.name), nil)
+ end
+ end
+ # keep/discard item
+ keep
+ }
end
# from css text, find font family definitions and construct google font url
diff --git a/projects/index.md b/projects/index.md
index 1d29a19944..0a257b451f 100644
--- a/projects/index.md
+++ b/projects/index.md
@@ -18,10 +18,10 @@ Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliqu
## Featured
-{% include list.html component="card" data="projects" filters="group: featured" %}
+{% include list.html component="card" data="projects" filter="group == 'featured'" %}
{% include section.html %}
## More
-{% include list.html component="card" data="projects" filters="group: " style="small" %}
+{% include list.html component="card" data="projects" filter="!group" style="small" %}
diff --git a/team/index.md b/team/index.md
index 08318c9183..c97b0da2cd 100644
--- a/team/index.md
+++ b/team/index.md
@@ -13,8 +13,8 @@ nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.
{% include section.html %}
-{% include list.html data="members" component="portrait" filters="role: pi" %}
-{% include list.html data="members" component="portrait" filters="role: ^(?!pi$)" %}
+{% include list.html data="members" component="portrait" filter="role == 'pi'" %}
+{% include list.html data="members" component="portrait" filter="role != 'pi'" %}
{% include section.html background="images/background.jpg" dark=true %}