datalog-theme 0.9.2 → 0.10.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,307 +0,0 @@
1
- {%- comment -%}
2
- Advanced Search with Facets/Filters
3
- Provides filtering by tags, categories, dates, and authors
4
-
5
- Parameters:
6
- - show_tags: Show tag filter (default: true)
7
- - show_categories: Show category filter (default: true)
8
- - show_dates: Show date filter (default: true)
9
- - show_authors: Show author filter (default: true)
10
- - show_difficulty: Show difficulty filter (default: true)
11
- {%- endcomment -%}
12
-
13
- {%- assign show_tags = include.show_tags | default: true -%}
14
- {%- assign show_categories = include.show_categories | default: true -%}
15
- {%- assign show_dates = include.show_dates | default: true -%}
16
- {%- assign show_authors = include.show_authors | default: true -%}
17
- {%- assign show_difficulty = include.show_difficulty | default: true -%}
18
-
19
- <div class="search-facets" data-search-facets>
20
- <div class="search-facets__header">
21
- <h2 class="search-facets__title">Filter & Search</h2>
22
- <button type="button"
23
- class="search-facets__reset"
24
- data-reset-filters
25
- aria-label="Reset all filters">
26
- Reset
27
- </button>
28
- </div>
29
-
30
- {%- comment -%} Search input {%- endcomment -%}
31
- <div class="search-facets__search">
32
- <label for="search-input" class="visually-hidden">Search posts</label>
33
- <input type="search"
34
- id="search-input"
35
- class="search-facets__input"
36
- placeholder="Search posts..."
37
- data-search-input
38
- aria-label="Search posts">
39
- <svg class="search-facets__search-icon" xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
40
- <circle cx="11" cy="11" r="8"></circle>
41
- <path d="m21 21-4.35-4.35"></path>
42
- </svg>
43
- </div>
44
-
45
- {%- comment -%} Filter panels {%- endcomment -%}
46
- <div class="search-facets__panels">
47
-
48
- {%- if show_tags -%}
49
- {%- comment -%} Collect all tags {%- endcomment -%}
50
- {%- assign all_tags = "" | split: "" -%}
51
- {%- for post in site.posts -%}
52
- {%- if post.tags -%}
53
- {%- assign all_tags = all_tags | concat: post.tags -%}
54
- {%- endif -%}
55
- {%- endfor -%}
56
- {%- assign unique_tags = all_tags | uniq | sort -%}
57
-
58
- {%- if unique_tags.size > 0 -%}
59
- <details class="search-facets__panel" open>
60
- <summary class="search-facets__panel-title">
61
- <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
62
- <path d="M20.59 13.41l-7.17 7.17a2 2 0 0 1-2.83 0L2 12V2h10l8.59 8.59a2 2 0 0 1 0 2.82z"></path>
63
- <line x1="7" y1="7" x2="7.01" y2="7"></line>
64
- </svg>
65
- Tags
66
- </summary>
67
- <div class="search-facets__options">
68
- {%- for tag in unique_tags limit: 20 -%}
69
- <label class="search-facets__checkbox">
70
- <input type="checkbox"
71
- value="{{ tag | slugify }}"
72
- data-filter="tag"
73
- aria-label="Filter by {{ tag }}">
74
- <span>{{ tag }}</span>
75
- </label>
76
- {%- endfor -%}
77
- </div>
78
- </details>
79
- {%- endif -%}
80
- {%- endif -%}
81
-
82
- {%- if show_categories -%}
83
- {%- comment -%} Collect all categories {%- endcomment -%}
84
- {%- assign all_categories = "" | split: "" -%}
85
- {%- for post in site.posts -%}
86
- {%- if post.categories -%}
87
- {%- assign all_categories = all_categories | concat: post.categories -%}
88
- {%- endif -%}
89
- {%- endfor -%}
90
- {%- assign unique_categories = all_categories | uniq | sort -%}
91
-
92
- {%- if unique_categories.size > 0 -%}
93
- <details class="search-facets__panel">
94
- <summary class="search-facets__panel-title">
95
- <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
96
- <path d="M22 19a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h5l2 3h9a2 2 0 0 1 2 2z"></path>
97
- </svg>
98
- Categories
99
- </summary>
100
- <div class="search-facets__options">
101
- {%- for category in unique_categories -%}
102
- <label class="search-facets__checkbox">
103
- <input type="checkbox"
104
- value="{{ category | slugify }}"
105
- data-filter="category"
106
- aria-label="Filter by {{ category }}">
107
- <span>{{ category }}</span>
108
- </label>
109
- {%- endfor -%}
110
- </div>
111
- </details>
112
- {%- endif -%}
113
- {%- endif -%}
114
-
115
- {%- if show_difficulty -%}
116
- <details class="search-facets__panel">
117
- <summary class="search-facets__panel-title">
118
- <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
119
- <path d="M21 16V8a2 2 0 0 0-1-1.73l-7-4a2 2 0 0 0-2 0l-7 4A2 2 0 0 0 3 8v8a2 2 0 0 0 1 1.73l7 4a2 2 0 0 0 2 0l7-4A2 2 0 0 0 21 16z"></path>
120
- </svg>
121
- Difficulty
122
- </summary>
123
- <div class="search-facets__options">
124
- <label class="search-facets__checkbox">
125
- <input type="checkbox" value="beginner" data-filter="difficulty" aria-label="Filter by beginner">
126
- <span>Beginner</span>
127
- </label>
128
- <label class="search-facets__checkbox">
129
- <input type="checkbox" value="intermediate" data-filter="difficulty" aria-label="Filter by intermediate">
130
- <span>Intermediate</span>
131
- </label>
132
- <label class="search-facets__checkbox">
133
- <input type="checkbox" value="advanced" data-filter="difficulty" aria-label="Filter by advanced">
134
- <span>Advanced</span>
135
- </label>
136
- <label class="search-facets__checkbox">
137
- <input type="checkbox" value="expert" data-filter="difficulty" aria-label="Filter by expert">
138
- <span>Expert</span>
139
- </label>
140
- </div>
141
- </details>
142
- {%- endif -%}
143
-
144
- {%- if show_dates -%}
145
- <details class="search-facets__panel">
146
- <summary class="search-facets__panel-title">
147
- <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
148
- <rect x="3" y="4" width="18" height="18" rx="2" ry="2"></rect>
149
- <line x1="16" y1="2" x2="16" y2="6"></line>
150
- <line x1="8" y1="2" x2="8" y2="6"></line>
151
- <line x1="3" y1="10" x2="21" y2="10"></line>
152
- </svg>
153
- Date Range
154
- </summary>
155
- <div class="search-facets__options">
156
- <label class="search-facets__checkbox">
157
- <input type="radio" name="date-range" value="week" data-filter="date" aria-label="Past week">
158
- <span>Past week</span>
159
- </label>
160
- <label class="search-facets__checkbox">
161
- <input type="radio" name="date-range" value="month" data-filter="date" aria-label="Past month">
162
- <span>Past month</span>
163
- </label>
164
- <label class="search-facets__checkbox">
165
- <input type="radio" name="date-range" value="year" data-filter="date" aria-label="Past year">
166
- <span>Past year</span>
167
- </label>
168
- <label class="search-facets__checkbox">
169
- <input type="radio" name="date-range" value="all" data-filter="date" checked aria-label="All time">
170
- <span>All time</span>
171
- </label>
172
- </div>
173
- </details>
174
- {%- endif -%}
175
- </div>
176
-
177
- {%- comment -%} Results count {%- endcomment -%}
178
- <div class="search-facets__results" data-results-count aria-live="polite">
179
- <span class="search-facets__count">{{ site.posts.size }}</span> posts found
180
- </div>
181
- </div>
182
-
183
- <script>
184
- (function() {
185
- 'use strict';
186
-
187
- document.addEventListener('DOMContentLoaded', function() {
188
- const facetsContainer = document.querySelector('[data-search-facets]');
189
- if (!facetsContainer) return;
190
-
191
- const searchInput = facetsContainer.querySelector('[data-search-input]');
192
- const resetButton = facetsContainer.querySelector('[data-reset-filters]');
193
- const resultsCount = facetsContainer.querySelector('[data-results-count] .search-facets__count]');
194
- const checkboxes = facetsContainer.querySelectorAll('[data-filter]');
195
-
196
- // Get all posts data
197
- const posts = Array.from(document.querySelectorAll('[data-post]')).map(post => ({
198
- element: post,
199
- title: post.dataset.title?.toLowerCase() || '',
200
- tags: post.dataset.tags?.toLowerCase().split(',') || [],
201
- categories: post.dataset.categories?.toLowerCase().split(',') || [],
202
- difficulty: post.dataset.difficulty?.toLowerCase() || '',
203
- date: new Date(post.dataset.date || 0),
204
- excerpt: post.dataset.excerpt?.toLowerCase() || ''
205
- }));
206
-
207
- function applyFilters() {
208
- const searchTerm = searchInput?.value.toLowerCase() || '';
209
- const activeFilters = {
210
- tags: [],
211
- categories: [],
212
- difficulty: [],
213
- date: 'all'
214
- };
215
-
216
- checkboxes.forEach(cb => {
217
- if (cb.checked) {
218
- const filterType = cb.dataset.filter;
219
- if (filterType === 'date') {
220
- activeFilters.date = cb.value;
221
- } else {
222
- activeFilters[filterType].push(cb.value);
223
- }
224
- }
225
- });
226
-
227
- let visibleCount = 0;
228
-
229
- posts.forEach(post => {
230
- let isVisible = true;
231
-
232
- // Search term filter
233
- if (searchTerm && !post.title.includes(searchTerm) && !post.excerpt.includes(searchTerm)) {
234
- isVisible = false;
235
- }
236
-
237
- // Tag filter
238
- if (activeFilters.tags.length > 0) {
239
- const hasTag = activeFilters.tags.some(tag => post.tags.includes(tag));
240
- if (!hasTag) isVisible = false;
241
- }
242
-
243
- // Category filter
244
- if (activeFilters.categories.length > 0) {
245
- const hasCategory = activeFilters.categories.some(cat => post.categories.includes(cat));
246
- if (!hasCategory) isVisible = false;
247
- }
248
-
249
- // Difficulty filter
250
- if (activeFilters.difficulty.length > 0 && !activeFilters.difficulty.includes(post.difficulty)) {
251
- isVisible = false;
252
- }
253
-
254
- // Date filter
255
- if (activeFilters.date !== 'all') {
256
- const now = new Date();
257
- const cutoff = new Date();
258
- switch (activeFilters.date) {
259
- case 'week':
260
- cutoff.setDate(now.getDate() - 7);
261
- break;
262
- case 'month':
263
- cutoff.setMonth(now.getMonth() - 1);
264
- break;
265
- case 'year':
266
- cutoff.setFullYear(now.getFullYear() - 1);
267
- break;
268
- }
269
- if (post.date < cutoff) isVisible = false;
270
- }
271
-
272
- // Show/hide post
273
- post.element.style.display = isVisible ? '' : 'none';
274
- if (isVisible) visibleCount++;
275
- });
276
-
277
- // Update count
278
- if (resultsCount) {
279
- resultsCount.textContent = visibleCount;
280
- }
281
- }
282
-
283
- // Event listeners
284
- if (searchInput) {
285
- searchInput.addEventListener('input', applyFilters);
286
- }
287
-
288
- checkboxes.forEach(cb => {
289
- cb.addEventListener('change', applyFilters);
290
- });
291
-
292
- if (resetButton) {
293
- resetButton.addEventListener('click', function() {
294
- if (searchInput) searchInput.value = '';
295
- checkboxes.forEach(cb => {
296
- if (cb.type === 'radio' && cb.value === 'all') {
297
- cb.checked = true;
298
- } else {
299
- cb.checked = false;
300
- }
301
- });
302
- applyFilters();
303
- });
304
- }
305
- });
306
- })();
307
- </script>