Skip to content

Commit 18011f8

Browse files
vintaclaude
andcommitted
feat: merge duplicate entries across multiple categories
Entries appearing in more than one category were previously emitted as separate rows. They are now deduplicated in build.py by URL, collecting all category and group names into lists. The template encodes those lists as pipe-delimited data attributes (data-cats, data-groups) and renders a tag button per category. The JS filter is updated to split on '||' and check for membership, so clicking any category tag correctly shows the merged row. Co-Authored-By: Claude <noreply@anthropic.com>
1 parent c537661 commit 18011f8

File tree

3 files changed

+30
-14
lines changed

3 files changed

+30
-14
lines changed

website/build.py

Lines changed: 20 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -243,29 +243,42 @@ def extract_entries(
243243
categories: list[dict],
244244
groups: list[dict],
245245
) -> list[dict]:
246-
"""Flatten categories into individual library entries for table display."""
246+
"""Flatten categories into individual library entries for table display.
247+
248+
Entries appearing in multiple categories are merged into a single entry
249+
with lists of categories and groups.
250+
"""
247251
cat_to_group: dict[str, str] = {}
248252
for group in groups:
249253
for cat in group["categories"]:
250254
cat_to_group[cat["name"]] = group["name"]
251255

256+
seen: dict[str, dict] = {} # url -> entry
252257
entries: list[dict] = []
253258
for cat in categories:
254259
group_name = cat_to_group.get(cat["name"], "Other")
255260
for entry in cat["entries"]:
256-
entries.append(
257-
{
261+
url = entry["url"]
262+
if url in seen:
263+
existing = seen[url]
264+
if cat["name"] not in existing["categories"]:
265+
existing["categories"].append(cat["name"])
266+
if group_name not in existing["groups"]:
267+
existing["groups"].append(group_name)
268+
else:
269+
merged = {
258270
"name": entry["name"],
259-
"url": entry["url"],
271+
"url": url,
260272
"description": entry["description"],
261-
"category": cat["name"],
262-
"group": group_name,
273+
"categories": [cat["name"]],
274+
"groups": [group_name],
263275
"stars": None,
264276
"owner": None,
265277
"last_commit_at": None,
266278
"also_see": entry["also_see"],
267279
}
268-
)
280+
seen[url] = merged
281+
entries.append(merged)
269282
return entries
270283

271284

website/static/main.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,8 @@ function applyFilters() {
5959

6060
// Category/group filter
6161
if (activeFilter) {
62-
show = row.dataset[activeFilter.type] === activeFilter.value;
62+
var attr = activeFilter.type === 'cat' ? row.dataset.cats : row.dataset.groups;
63+
show = attr ? attr.split('||').indexOf(activeFilter.value) !== -1 : false;
6364
}
6465

6566
// Text search

website/templates/index.html

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -84,8 +84,8 @@ <h2 class="sr-only">Results</h2>
8484
<tr
8585
class="row"
8686
role="button"
87-
data-cat="{{ entry.category }}"
88-
data-group="{{ entry.group }}"
87+
data-cats="{{ entry.categories | join('||') }}"
88+
data-groups="{{ entry.groups | join('||') }}"
8989
tabindex="0"
9090
aria-expanded="false"
9191
aria-controls="expand-{{ loop.index }}"
@@ -116,11 +116,13 @@ <h2 class="sr-only">Results</h2>
116116
>{% else %}&mdash;{% endif %}
117117
</td>
118118
<td class="col-cat">
119-
<button class="tag" data-type="cat" data-value="{{ entry.category }}">
120-
{{ entry.category }}
119+
{% for cat in entry.categories %}
120+
<button class="tag" data-type="cat" data-value="{{ cat }}">
121+
{{ cat }}
121122
</button>
122-
<button class="tag tag-group" data-type="group" data-value="{{ entry.group }}">
123-
{{ entry.group }}
123+
{% endfor %}
124+
<button class="tag tag-group" data-type="group" data-value="{{ entry.groups[0] }}">
125+
{{ entry.groups[0] }}
124126
</button>
125127
</td>
126128
<td class="col-arrow"><span class="arrow">&rarr;</span></td>

0 commit comments

Comments
 (0)