Skip to content

Commit b0f74ae

Browse files
committed
Re-adds filters to Site Generators page
1 parent f8a197b commit b0f74ae

File tree

25 files changed

+224
-39
lines changed

25 files changed

+224
-39
lines changed

.eleventy.js

Lines changed: 26 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,8 @@
11
const lodashGet = require("lodash/get");
2+
const yaml = require("js-yaml");
23

34
module.exports = function(eleventyConfig) {
4-
55
// Support yaml data files
6-
const yaml = require("js-yaml");
76
eleventyConfig.addDataExtension("yaml", contents => yaml.safeLoad(contents))
87

98
// pass images directly through to the output
@@ -69,9 +68,31 @@ module.exports = function(eleventyConfig) {
6968

7069
// filter a data array based on the value of a property
7170
eleventyConfig.addFilter('select', (array, clause) => {
72-
const property = clause.split("=")[0];
73-
const value = clause.split("=")[1];
74-
return array.filter(item => item[property].includes(value));
71+
if(clause.indexOf("=") > -1) {
72+
const property = clause.split("=")[0];
73+
const value = clause.split("=")[1];
74+
return array.filter(item => lodashGet(item, property).includes(value));
75+
} else {
76+
return array.map(item => lodashGet(item, clause));
77+
}
78+
});
79+
80+
eleventyConfig.addFilter('flatten', (array) => {
81+
let results = [];
82+
for(let result of array) {
83+
if(result) {
84+
if(Array.isArray(result)) {
85+
results = [...results, ...result];
86+
} else {
87+
results.push(result);
88+
}
89+
}
90+
}
91+
return results;
92+
});
93+
94+
eleventyConfig.addFilter('unique', (array) => {
95+
return [...new Set(array)];
7596
});
7697

7798
// Get a random selection of items from an array

src/css/tailwind.css

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -314,6 +314,13 @@ details[open] .summary-swap-open {
314314
.tool-content img {
315315
@apply my-8;
316316
}
317+
318+
/* Filters */
319+
.filter-language--hide,
320+
.filter-template--hide,
321+
.filter-license--hide {
322+
display: none !important;
323+
}
317324
/* purgecss end ignore */
318325

319326
@tailwind utilities;

src/js/filter-container.js

Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
class FilterContainer extends HTMLElement {
2+
constructor() {
3+
super();
4+
this.attrs = {
5+
bind: "data-filter-bind",
6+
delimiter: "data-filter-delimiter",
7+
results: "data-filter-results",
8+
};
9+
this.classes = {
10+
hidden: "filter--hide",
11+
}
12+
}
13+
14+
connectedCallback() {
15+
this.results = this.querySelector(`[${this.attrs.results}]`);
16+
let formElements = this.getAllFormElements();
17+
this.bindEvents(formElements);
18+
this.filterAll(formElements);
19+
}
20+
21+
getAllFormElements() {
22+
return this.querySelectorAll(`[${this.attrs.bind}]`);
23+
}
24+
25+
getAllKeys() {
26+
let keys = new Set();
27+
for(let formEl of this.getAllFormElements()) {
28+
keys.add(formEl.getAttribute(this.attrs.bind));
29+
}
30+
return Array.from(keys);
31+
}
32+
33+
getElementSelector(key) {
34+
return `data-filter-${key}`
35+
}
36+
37+
getAllFilterableElements() {
38+
let keys = this.getAllKeys();
39+
let selector = keys.map(key => {
40+
return `[${this.getElementSelector(key)}]`;
41+
}).join(",");
42+
return this.querySelectorAll(selector);
43+
}
44+
45+
bindEvents(formElements) {
46+
for(let el of formElements) {
47+
el.addEventListener("change", e => {
48+
this.filter(e.target);
49+
requestAnimationFrame(() => {
50+
this.renderResultCount();
51+
})
52+
}, false);
53+
}
54+
}
55+
56+
filterAll(formElements) {
57+
for(let el of formElements) {
58+
this.filter(el);
59+
}
60+
this.renderResultCount();
61+
}
62+
63+
filter(formElement) {
64+
let key = formElement.getAttribute(this.attrs.bind);
65+
let delimiter = formElement.getAttribute(this.attrs.delimiter);
66+
67+
let value = formElement.value;
68+
let elementsSelectorAttr = this.getElementSelector(key);
69+
70+
let elements = this.querySelectorAll(`[${elementsSelectorAttr}]`);
71+
let count = 0;
72+
let cls = `filter-${key}--hide`;
73+
for(let element of Array.from(elements)) {
74+
if(this.elementIsValid(element, elementsSelectorAttr, value, delimiter)) {
75+
element.classList.remove(cls);
76+
} else {
77+
element.classList.add(cls);
78+
}
79+
}
80+
}
81+
82+
elementIsValid(element, attributeName, value, delimiter) {
83+
if(!value) {
84+
return true;
85+
}
86+
let attrValue = element.getAttribute(attributeName);
87+
if(delimiter && attrValue.split(delimiter).indexOf(value) > -1) {
88+
return true;
89+
}
90+
if(!delimiter && attrValue === value) {
91+
return true;
92+
}
93+
return false;
94+
}
95+
96+
elementIsVisible(element) {
97+
for(let cls of element.classList) {
98+
if(cls.startsWith("filter-") && cls.endsWith("--hide")) {
99+
return false;
100+
}
101+
}
102+
return true;
103+
}
104+
105+
renderResultCount() {
106+
let count = Array.from(this.getAllFilterableElements())
107+
.filter(entry => this.elementIsVisible(entry))
108+
.length;
109+
110+
this.results.innerHTML = `${count} Result${count !== 1 ? "s" : ""}`;
111+
}
112+
}
113+
114+
window.customElements.define("filter-container", FilterContainer);

src/site/_data/github.js

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -102,11 +102,13 @@ async function getReposFromMarkdown(glob) {
102102
let split = fullRepo.split("/");
103103
let user = split[0];
104104
let repo = split[1];
105-
if(!matter.data.repohost || matter.data.repohost === "github")
106-
repos.push({ user, repo });
107-
} else {
108-
// TODO maybe just log this in production?
109-
// console.log( "GitHub full repo not found for", ssg );
105+
106+
if(!matter.data.repohost || matter.data.repohost === "github") {
107+
if(matter.data.disabled) {
108+
continue;
109+
}
110+
repos.push({ user, repo });
111+
}
110112
}
111113
}
112114

src/site/_includes/components/cards.njk

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
11
{% macro repo(item, loopIndex, githubData) %}
2-
<div id="{{item.id}}" class="generator-card flex flex-col h-full">
2+
<div id="{{item.id}}" class="generator-card flex flex-col h-full"
3+
data-filter-template="{%- if item.data.templates %}{{ item.data.templates | join(",") | lower }}{% endif %}"
4+
data-filter-language="{%- if item.data.language %}{{ item.data.language | join(",") | lower }}{% endif %}"
5+
data-filter-license="{%- if item.data.license %}{{ item.data.license | join(",") | lower }}{% endif %}">
36
<a href="{{ item.url }}" class="flex-grow block border-0 bg-white text-gray-700 rounded-t-lg last:rounded-b-lg">
4-
<div class="text-xl md:text-2xl lg:text-3xl font-bold text-ellipsis text-black bg-gradient-to-b border-b rounded-t-lg p-4
7+
<div class="text-xl md:text-2xl lg:text-3xl font-bold text-ellipsis text-black bg-gradient-to-b border-b border-black rounded-t-lg p-4
58
{%- if loopIndex % 4 === 0 %} bg-gradient-card-sunrise
69
{%- elseif loopIndex % 4 === 1 %} bg-gradient-card-blue
710
{%- elseif loopIndex % 4 === 2 %} bg-gradient-card-seafoam
@@ -69,7 +72,7 @@
6972
</div>
7073
</a>
7174
{% if item.data.startertemplaterepo %}
72-
<a href="https://app.netlify.com/start/deploy?repository={{ item.data.startertemplaterepo}}" class="block px-4 py-3 text-gray-700 bg-white rounded-b-lg text-center md:text-lg whitespace-no-wrap border-t">
75+
<a href="https://app.netlify.com/start/deploy?repository={{ item.data.startertemplaterepo}}" class="block px-4 py-3 text-gray-700 bg-white rounded-b-lg text-center md:text-lg whitespace-nowrap border-t">
7376
<svg role="img" aria-hidden="true" focusable="false" width="30" height="30" viewBox="0 0 40 40" class="inline-block mr-1" fill="#36b0bb"><use xlink:href="#logo-netlify-gem"/></svg>
7477
Deploy to Netlify
7578
</a>

src/site/_includes/layouts/base.njk

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,5 +92,6 @@ ogimage: "/img/og/default-og-image.png"
9292
</defs>
9393
</svg>
9494
<script type="module" src="/js/details-force-state.js"></script>
95+
<script type="module" src="/js/filter-container.js"></script>
9596
</body>
9697
</html>

src/site/_includes/layouts/tool.njk

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -33,21 +33,21 @@ layout: layouts/base.njk
3333
<dl class="inline-block mt-4 mb-4">
3434
{%- if homepage %}
3535
<dt class="sr-only">Home page</dt>
36-
<dd class="inline-block mr-6 whitespace-no-wrap">
36+
<dd class="inline-block mr-6 whitespace-nowrap">
3737
<svg role="img" aria-hidden="true" focusable="false" width="20" height="20" class="fill-current inline-block mr-1"><use xlink:href="#icon-home"/></svg>
3838
<a href="{{ homepage }}" target="_blank" rel="noopener">{{ homepage }}</a>
3939
</dd>
4040
{%- endif %}
4141
{%- if repo %}
4242
<dt class="sr-only">Repository</dt>
43-
<dd class="inline-block mr-6 whitespace-no-wrap">
43+
<dd class="inline-block mr-6 whitespace-nowrap">
4444
<svg role="img" aria-hidden="true" focusable="false" width="20" height="20" class="fill-current inline-block mr-1"><use xlink:href="#icon-github"/></svg>
4545
<a href="{% if not repohost or repohost == "github" %}https://github.com/{% endif %}{% if repohost == "gitlab" %}https://gitlab.com/{% endif %}{{ repo }}" target="_blank" rel="noopener">{{ repo }}</a>
4646
</dd>
4747
{%- endif %}
4848
{%- if twitter %}
4949
<dt class="sr-only">Twitter</dt>
50-
<dd class="inline-block mr-6 whitespace-no-wrap">
50+
<dd class="inline-block mr-6 whitespace-nowrap">
5151
<svg role="img" aria-hidden="true" focusable="false" width="20" height="20" class="fill-current inline-block mr-1"><use xlink:href="#icon-twitter"/></svg>
5252
<a href="https://twitter.com/{{ twitter }}/" target="_blank" rel="noopener">@{{ twitter }}</a>
5353
</dd>
@@ -89,7 +89,7 @@ layout: layouts/base.njk
8989

9090

9191
{% if startertemplaterepo %}
92-
<a href="https://app.netlify.com/start/deploy?repository={{ startertemplaterepo }}" class="inline-block my-8 px-4 py-3 text-gray-700 bg-white rounded-lg text-center md:text-lg whitespace-no-wrap border-t">
92+
<a href="https://app.netlify.com/start/deploy?repository={{ startertemplaterepo }}" class="inline-block my-8 px-4 py-3 text-gray-700 bg-white rounded-lg text-center md:text-lg whitespace-nowrap border-t">
9393
<svg role="img" aria-hidden="true" focusable="false" width="30" height="30" viewBox="0 0 40 40" class="inline-block mr-1" fill="#36b0bb"><use xlink:href="#logo-netlify-gem"/></svg>
9494
Deploy to Netlify
9595
</a>

src/site/generators.njk

Lines changed: 40 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -13,11 +13,46 @@ layout: layouts/base.njk
1313
</section>
1414

1515
<section class="cards mt-12">
16-
<div class="grid gap-4 grid-cols-1 md:grid-cols-2 lg:grid-cols-3">
17-
{% for item in collections.generators | sortTools(github) %}
18-
{{ cards.repo(item, loop.index0, github) }}
19-
{% endfor %}
20-
</div>
16+
<filter-container>
17+
<form class="pb-4">
18+
<div class="pb-2">
19+
<strong class="pr-4">Filter</strong>
20+
<span data-filter-results></span>
21+
</div>
22+
<label class="inline-flex pr-4 pb-2">
23+
<span class="sr-only">Language</span>
24+
<select data-filter-bind="language" data-filter-delimiter="," class="text-white py-1 rounded border border-white bg-transparent">
25+
<option selected value="">All Languages</option>
26+
{%- for language in collections.generators | select("data.language") | flatten | unique | sort(false, false) %}
27+
<option value="{{ language | lower }}">{{ language }}</option>
28+
{%- endfor %}
29+
</select>
30+
</label>
31+
<label class="inline-flex pr-4 pb-2">
32+
<span class="sr-only">Template</span>
33+
<select data-filter-bind="template" data-filter-delimiter="," class="text-white py-1 rounded border border-white bg-transparent">
34+
<option selected value="">All Templates</option>
35+
{%- for template in collections.generators | select("data.templates") | flatten | unique | sort(false, false) %}
36+
<option value="{{ template | lower }}">{{ template }}</option>
37+
{%- endfor %}
38+
</select>
39+
</label>
40+
<label class="inline-flex pr-4 pb-2">
41+
<span class="sr-only">License</span>
42+
<select data-filter-bind="license" data-filter-delimiter="," class="text-white py-1 rounded border border-white bg-transparent">
43+
<option selected value="">All Licenses</option>
44+
{%- for license in collections.generators | select("data.license") | flatten | unique | sort(false, false) %}
45+
<option value="{{ license | lower }}">{{ license }}</option>
46+
{%- endfor %}
47+
</select>
48+
</label>
49+
</form>
50+
<div class="grid gap-4 grid-cols-1 md:grid-cols-2 lg:grid-cols-3">
51+
{% for item in collections.generators | sortTools(github) %}
52+
{{ cards.repo(item, loop.index0, github) }}
53+
{% endfor %}
54+
</div>
55+
</filter-container>
2156
</section>
2257

2358
<section class="mt-12">

src/site/generators/ago.md

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,8 @@ homepage: https://github.com/dvwallin/ago
55
language:
66
- Go
77
license:
8-
- MIT License
8+
- MIT
99
templates:
10-
- None
1110
description: A static blog generator script without any fuzz
1211
---
1312

src/site/generators/bashblog-ng.md

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@ language:
77
license:
88
- GPL-3.0-only
99
templates:
10-
- None
1110
description: Bash script to create and manage blogs.
1211
---
1312

0 commit comments

Comments
 (0)