Skip to content

Commit 4067a90

Browse files
author
doomy
committed
sortable crates
1 parent c21e1ab commit 4067a90

4 files changed

Lines changed: 205 additions & 54 deletions

File tree

content/crates.toml

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
[[crates]]
2+
source = "crates"
3+
key = "fundsp"
4+
5+
[[crates]]
6+
source = "crates"
7+
key = "cpal"
8+
9+
[[crates]]
10+
source = "crates"
11+
key = "coremidi"
12+
13+
[[crates]]
14+
source = "github"
15+
key = "wrl/baseplug"
16+
17+
[[crates]]
18+
source = "github"
19+
key = "RustAudio/baseview"
20+
21+
[[crates]]
22+
source = "github"
23+
key = "robbert-vdh/nih-plug"
24+
25+
[[crates]]
26+
source = "github"
27+
key = "glowcoil/clap-sys"
28+

sass/_colors.scss

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ $border: #e1d8dd;
22
$background: #ffffff;
33
$background-low: #f3f3f3;
44
$primary: #09184f;
5+
$accent: #0529ab;
56
$contrast: darken($primary, 10);
67
$contrast-low: lighten(desaturate($primary, 70), 20);
78
$shadow: 0px 0px 3px 0px #1110121a;

sass/main.scss

Lines changed: 27 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -46,10 +46,11 @@ body {
4646
font-family: Arial, Helvetica, sans-serif;
4747
background: $background;
4848
margin: 0;
49+
margin-bottom: 8em;
4950
a {text-decoration: none; }
5051
}
5152

52-
a.button {
53+
.button {
5354
background: $primary;
5455
font-weight: 700;
5556
padding: 0.5em 1em;
@@ -64,7 +65,18 @@ a.button {
6465
}
6566
}
6667

67-
a.tag {
68+
.filters {
69+
margin-bottom: 1em;
70+
}
71+
72+
.tags {
73+
display: flex;
74+
flex-wrap: wrap;
75+
gap: 0.3em;
76+
align-items: flex-start;
77+
}
78+
79+
.tag {
6880
background: $background-low;
6981
font-weight: 600;
7082
padding: 0.1em 0.6em;
@@ -75,6 +87,7 @@ a.tag {
7587
font-size: 0.8rem;
7688
vertical-align: baseline;
7789
i{height: 0; svg{width:16px}}
90+
cursor: pointer;
7891
&:hover {
7992
background: darken($background-low, 5);
8093
}
@@ -83,6 +96,12 @@ a.tag {
8396
}
8497
}
8598

99+
.tag.toggled {
100+
background: $accent;
101+
border: 1px solid rgba(255, 255, 255, 0.5);
102+
color: $background;
103+
}
104+
86105
i{
87106
vertical-align: middle;
88107
svg {
@@ -182,47 +201,21 @@ section {
182201
margin: 0;
183202
}
184203
.crate {
185-
border-bottom: 1px $border solid;
186-
border-right: 1px $border solid;
187-
@media screen and ( min-width: 960px) {
188-
&:nth-child(4n), &:last-child {
189-
border-right: none;
190-
}
191-
&:nth-child(-n+4) {
192-
border-top: 1px $border solid;
193-
}
194-
}
195-
@media screen and (max-width: 960px) and (min-width: 720px) {
196-
&:nth-child(3n), &:last-child {
197-
border-right: none;
198-
}
199-
&:nth-child(-n+3) {
200-
border-top: 1px $border solid;
201-
}
202-
}
203-
@media screen and (max-width: 720px) and (min-width: 500px) {
204-
&:nth-child(2n), &:last-child {
205-
border-right: none;
206-
}
207-
&:nth-child(-n+2) {
208-
border-top: 1px $border solid;
209-
}
210-
}
211-
@media screen and (max-width: 500px) {
212-
border: none;
213-
border-top: 1px $border solid;
214-
}
204+
border-top: 1px $border solid;
215205
display: flex;
216-
justify-content: space-between;
206+
flex-direction: column;
217207
padding: 1em;
218-
gap: 1em;
208+
gap: 0.4em 1em;
219209
.details {
220210
display: flex;
221211
gap: 0.5em;
222212
align-items: center;
223213
}
224214
p, pre {
225215
margin: 0;
216+
font-size: 0.8em;
217+
line-height: 1.4;
226218
}
219+
227220
}
228221
}

templates/index.html

Lines changed: 149 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,79 @@ <h4 style="margin: 0;">Forums</h4>
4444

4545
<hr>
4646

47+
{# Crates #}
48+
49+
50+
<section>
51+
<div class="container-full">
52+
<h2>Audio crates</h2>
53+
<div class="filters tags"></div>
54+
</div>
55+
<div class="crates" id="crates">
56+
{% set crates = load_data(path="content/crates.toml") %}
57+
{% for source, crates in crates.crates | group_by(attribute="source") %}
58+
59+
{% for crate in crates %}
60+
61+
{# Obtain API data #}
62+
{% if source == "github" %}
63+
{# Get github API page to pull information #}
64+
{% set data = load_data(url="https://api.github.com/repos/"~crate.key, format="json") %}
65+
{% set name = data.name %}
66+
{% set description = data.description %}
67+
{% set url = data.svn_url %}
68+
{% set keywords = data.topics %}
69+
70+
{% elif source == "crates" %}
71+
{# Get crates API page to pull information #}
72+
{% set data = load_data(url="https://crates.io/api/v1/crates/"~crate.key, format="json") %}
73+
{% set name = data.crate.name %}
74+
{% set description = data.crate.description %}
75+
{% set url = "https://crates.io/crates/"~name %}
76+
{% set keywords = data.crate.keywords %}
77+
78+
{% endif %}
79+
80+
<div class='crate' data-keywords='{{ keywords | join(sep=" ") }}'>
81+
<a target=" _blank" href={{url}}>
82+
<h4>
83+
<pre>{{ name }}</pre>
84+
</h4>
85+
</a>
86+
<p>{{ description }}</p>
87+
88+
<div class="tags">
89+
{% for keyword in keywords %}
90+
<span class="filter-tag tag" data-keyword={{keyword}}>{{keyword}}</span>
91+
{% endfor %}
92+
</div>
93+
{# <div class="details">
94+
<div class="stars">{{ crate.stargazers_count }} ☆</div>
95+
</div> #}
96+
</div>
97+
{% endfor %}
98+
{% endfor %}
99+
</div>
100+
101+
{# <div class="crates">
102+
{% set crates = load_data(url=config.extra.repos_url, format="json") %}
103+
{% for crate in crates | sort(attribute="updated_at") | reverse %}
104+
<div class="crate">
105+
<a target="_blank" href={{crate.svn_url}}>
106+
<h5>
107+
<pre>{{ crate.name }}</pre>
108+
</h5>
109+
</a>
110+
<div class="details">
111+
<div class="stars">{{ crate.stargazers_count }} ☆</div>
112+
</div>
113+
</div>
114+
{% endfor %}
115+
</div> #}
116+
</section>
117+
118+
<hr>
119+
47120
{# Resources #}
48121
<section class="container">
49122
<h2>Resources</h2>
@@ -108,27 +181,83 @@ <h2>{{group | capitalize}}</h2>
108181
</article>
109182
</section>
110183

111-
<hr>
184+
<script>
185+
(function () {
112186

113-
{# Crates #}
187+
var element = document.querySelector("#crates");
188+
let tags = document.querySelectorAll(".filter-tag");
189+
var filter_element = document.querySelector(".filters");
190+
var filters = [];
191+
[].forEach.call(tags, function (tag) {
192+
filters.push(tag.innerText)
193+
});
194+
// Dedup
195+
filters = [...new Set(filters)].sort();
196+
enabled_filters = []
114197

115-
<section>
116-
<h2 class="container-full">Rust Audio Crates</h2>
117-
<div class="crates">
118-
{% set crates = load_data(url=config.extra.repos_url, format="json") %}
119-
{% for crate in crates | sort(attribute="updated_at") | reverse %}
120-
<div class="crate">
121-
<a target="_blank" href={{crate.svn_url}}>
122-
<h5>
123-
<pre>{{ crate.name }}</pre>
124-
</h5>
125-
</a>
126-
<div class="details">
127-
<div class="stars">{{ crate.stargazers_count }} ☆</div>
128-
</div>
129-
</div>
130-
{% endfor %}
131-
</div>
132-
</section>
198+
function build_filters() {
199+
filter_element.innerHTML = "";
200+
filters.forEach((filter) => {
201+
var filter_el = document.createElement("DIV");
202+
filter_el.classList.add("tag");
203+
filter_el.classList.add("filter-tag");
204+
filter_el.dataset.keyword = filter;
205+
filter_el.innerText = filter;
206+
filter_element.appendChild(filter_el);
207+
});
208+
}
209+
210+
function filter_entries() {
211+
// Get all filterable elements
212+
let elements = document.querySelectorAll("#crates .crate");
213+
[].forEach.call(elements, function (el) {
214+
let keywords = el.dataset.keywords.split(" ");
215+
let is_active = keywords.some(r => enabled_filters.indexOf(r) >= 0);
216+
if (enabled_filters.length == 0) {
217+
el.style.display = "block";
218+
} else {
219+
if (!is_active) {
220+
el.style.display = "none";
221+
} else {
222+
el.style.display = "block";
223+
}
224+
}
225+
});
226+
}
227+
228+
function toggle_filter(keyword) {
229+
let tags_with_keyword = document.querySelectorAll(`[data-keyword="${keyword}"]`);
230+
let index = enabled_filters.indexOf(keyword);
231+
if (index > -1) {
232+
console.log("toggling off tag");
233+
// exists, toggle off
234+
enabled_filters.splice(index, 1);
235+
[].forEach.call(tags_with_keyword, function (el) {
236+
el.classList.remove("toggled");
237+
});
238+
} else {
239+
console.log("toggling on tag");
240+
// doesn't yet exist, push
241+
enabled_filters.push(keyword);
242+
// toggle style for all tags
243+
[].forEach.call(tags_with_keyword, function (el) {
244+
el.classList.add("toggled");
245+
});
246+
}
247+
filter_entries();
248+
}
249+
250+
build_filters();
251+
252+
tags = document.querySelectorAll(".filter-tag");
253+
[].forEach.call(tags, function (tag) {
254+
tag.addEventListener("click", (ev) => {
255+
let keyword = tag.innerText;
256+
toggle_filter(keyword);
257+
});
258+
});
259+
260+
})();
261+
</script>
133262

134263
{% endblock content %}

0 commit comments

Comments
 (0)