|
|
@ -54,7 +54,7 @@ article h1 {
|
|
54
|
54
|
}
|
|
55
|
55
|
|
|
56
|
56
|
article header .permalink {
|
|
57
|
|
margin-left: 0.1em;
|
|
|
57
|
margin-left: 0.5em;
|
|
58
|
58
|
text-decoration: none;
|
|
59
|
59
|
color: #555;
|
|
60
|
60
|
|
|
|
@ -66,7 +66,7 @@ article header:hover .permalink {
|
|
66
|
66
|
}
|
|
67
|
67
|
|
|
68
|
68
|
article time {
|
|
69
|
|
margin-left: 1em;
|
|
|
69
|
margin-left: 0.5em;
|
|
70
|
70
|
color: #666;
|
|
71
|
71
|
}
|
|
72
|
72
|
|
|
|
@ -249,52 +249,66 @@ func main() {
|
|
249
|
249
|
fmt.Fprintf(out, `
|
|
250
|
250
|
|
|
251
|
251
|
<script>
|
|
|
252
|
var baseTitle = document.title;
|
|
|
253
|
|
|
252
|
254
|
var currentFilter = null;
|
|
253
|
255
|
|
|
254
|
256
|
window.addEventListener("DOMContentLoaded", function(ev) {
|
|
255
|
|
filterFromURL(document.location);
|
|
|
257
|
runFilterFromURL(document.location);
|
|
256
|
258
|
});
|
|
257
|
259
|
|
|
258
|
260
|
window.addEventListener("hashchange", function(ev) {
|
|
259
|
|
filterFromURL(new URL(ev.newURL));
|
|
|
261
|
runFilterFromURL(new URL(ev.newURL));
|
|
260
|
262
|
});
|
|
261
|
263
|
|
|
262
|
264
|
window.addEventListener("click", function(ev) {
|
|
263
|
|
if (ev.target.classList.contains("tag-link")) {
|
|
264
|
|
if (ev.target.href == "") {
|
|
265
|
|
return;
|
|
266
|
|
}
|
|
|
265
|
if (!ev.target.classList.contains("tag-link")) {
|
|
|
266
|
return;
|
|
|
267
|
}
|
|
267
|
268
|
|
|
268
|
|
var tag = tagFromURL(new URL(ev.target.href));
|
|
269
|
|
if (currentFilter == tag) {
|
|
270
|
|
clearFilter();
|
|
271
|
|
location.hash = "";
|
|
272
|
|
ev.preventDefault();
|
|
273
|
|
} else {
|
|
274
|
|
filterTag(tag);
|
|
275
|
|
}
|
|
|
269
|
if (ev.target.href == "") {
|
|
|
270
|
return;
|
|
276
|
271
|
}
|
|
277
|
|
});
|
|
278
|
272
|
|
|
279
|
|
function filterFromURL(u) {
|
|
280
|
|
var tag = tagFromURL(u);
|
|
281
|
|
if (tag == null) {
|
|
|
273
|
var filter = filterFromURL(new URL(ev.target.href));
|
|
|
274
|
if (isSameFilter(currentFilter, filter)) {
|
|
282
|
275
|
clearFilter();
|
|
|
276
|
location.hash = "";
|
|
|
277
|
ev.preventDefault();
|
|
283
|
278
|
} else {
|
|
284
|
279
|
filterTag(tag);
|
|
285
|
280
|
}
|
|
|
281
|
});
|
|
|
282
|
|
|
|
283
|
function isSameFilter(f1, f2) {
|
|
|
284
|
return f1 && f2 && f1.type == f2.type && f1.argument == f2.argument;
|
|
286
|
285
|
}
|
|
287
|
286
|
|
|
288
|
|
function tagFromURL(u) {
|
|
289
|
|
if (!u.hash.startsWith("#tag:")) {
|
|
|
287
|
function runFilterFromURL(u) {
|
|
|
288
|
var filter = filterFromURL(u);
|
|
|
289
|
if (filter == null) {
|
|
|
290
|
clearFilter();
|
|
|
291
|
} else {
|
|
|
292
|
filter.run(filter.argument);
|
|
|
293
|
currentFilter = filter;
|
|
|
294
|
}
|
|
|
295
|
}
|
|
|
296
|
|
|
|
297
|
function filterFromURL(u) {
|
|
|
298
|
if (u.hash.startsWith("#tag:")) {
|
|
|
299
|
return { type: "tag", run: filterTag, argument: u.hash.substr(5) };
|
|
|
300
|
} else if (u.hash.startsWith("#title:")) {
|
|
|
301
|
return { type: "title", run: filterTitle, argument: u.hash.substr(7) };
|
|
|
302
|
} else if (u.hash.startsWith("#id:")) {
|
|
|
303
|
return { type: "id", run: filterId, argument: u.hash.substr(4) };
|
|
|
304
|
} else if (u.hash.startsWith("#type:")) {
|
|
|
305
|
return { type: "type", run: filterType, argument: u.hash.substr(6) };
|
|
|
306
|
} else {
|
|
290
|
307
|
return null;
|
|
291
|
308
|
}
|
|
292
|
|
return u.hash.substr(5);
|
|
293
|
309
|
}
|
|
294
|
310
|
|
|
295
|
311
|
function filterTag(tag) {
|
|
296
|
|
currentFilter = tag;
|
|
297
|
|
|
|
298
|
312
|
var articles = document.querySelectorAll("article");
|
|
299
|
313
|
for (var i = 0; i < articles.length; i++) {
|
|
300
|
314
|
var article = articles[i];
|
|
|
@ -308,10 +322,58 @@ func main() {
|
|
308
|
322
|
}
|
|
309
|
323
|
}
|
|
310
|
324
|
}
|
|
311
|
|
if (!matches) {
|
|
|
325
|
if (matches) {
|
|
|
326
|
article.classList.remove("does-not-match");
|
|
|
327
|
} else {
|
|
312
|
328
|
article.classList.add("does-not-match");
|
|
313
|
329
|
}
|
|
314
|
330
|
}
|
|
|
331
|
|
|
|
332
|
document.title = baseTitle + " (Posts tagged '" + tag + "')";
|
|
|
333
|
}
|
|
|
334
|
|
|
|
335
|
function filterTitle(match) {
|
|
|
336
|
var match = match.toLowerCase();
|
|
|
337
|
var articles = document.querySelectorAll("article");
|
|
|
338
|
for (var i = 0; i < articles.length; i++) {
|
|
|
339
|
var article = articles[i];
|
|
|
340
|
var title = article.querySelector("header h1");
|
|
|
341
|
if (title && title.textContent.toLowerCase().match(match)) {
|
|
|
342
|
article.classList.remove("does-not-match");
|
|
|
343
|
} else {
|
|
|
344
|
article.classList.add("does-not-match");
|
|
|
345
|
}
|
|
|
346
|
}
|
|
|
347
|
|
|
|
348
|
document.title = baseTitle + " (Posts matching '" + match + "')";
|
|
|
349
|
}
|
|
|
350
|
|
|
|
351
|
function filterId(id) {
|
|
|
352
|
var articles = document.querySelectorAll("article");
|
|
|
353
|
for (var i = 0; i < articles.length; i++) {
|
|
|
354
|
var article = articles[i];
|
|
|
355
|
if (article.id == id) {
|
|
|
356
|
article.classList.remove("does-not-match");
|
|
|
357
|
} else {
|
|
|
358
|
article.classList.add("does-not-match");
|
|
|
359
|
}
|
|
|
360
|
}
|
|
|
361
|
|
|
|
362
|
document.title = baseTitle + " (Only post id '" + id + "')";
|
|
|
363
|
}
|
|
|
364
|
|
|
|
365
|
function filterType(type) {
|
|
|
366
|
var articles = document.querySelectorAll("article");
|
|
|
367
|
for (var i = 0; i < articles.length; i++) {
|
|
|
368
|
var article = articles[i];
|
|
|
369
|
if (article.classList.contains(type)) {
|
|
|
370
|
article.classList.remove("does-not-match");
|
|
|
371
|
} else {
|
|
|
372
|
article.classList.add("does-not-match");
|
|
|
373
|
}
|
|
|
374
|
}
|
|
|
375
|
|
|
|
376
|
document.title = baseTitle + " (Only " + type + " posts)";
|
|
315
|
377
|
}
|
|
316
|
378
|
|
|
317
|
379
|
function clearFilter() {
|
|
|
@ -321,6 +383,7 @@ func main() {
|
|
321
|
383
|
}
|
|
322
|
384
|
|
|
323
|
385
|
currentFilter = null;
|
|
|
386
|
document.title = baseTitle;
|
|
324
|
387
|
}
|
|
325
|
388
|
</script>`)
|
|
326
|
389
|
fmt.Fprintf(out, "\n</body>\n</html>\n")
|