@binarynoir/vitepress-blog 0.4.0 → 0.5.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.
- package/README.md +40 -22
- package/dist/{chunk-ZM5FOUT4.js → chunk-FPFH7ORO.js} +63 -36
- package/dist/chunk-FPFH7ORO.js.map +1 -0
- package/dist/client.cjs +73 -5
- package/dist/client.cjs.map +1 -1
- package/dist/client.js +73 -5
- package/dist/client.js.map +1 -1
- package/dist/index.cjs +62 -35
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/{plugin-DUTUA_t4.d.cts → plugin-kzO68Abz.d.cts} +15 -1
- package/dist/{plugin-DUTUA_t4.d.ts → plugin-kzO68Abz.d.ts} +15 -1
- package/dist/style.css +146 -22
- package/dist/vitepress.cjs +62 -35
- package/dist/vitepress.cjs.map +1 -1
- package/dist/vitepress.d.cts +2 -2
- package/dist/vitepress.d.ts +2 -2
- package/dist/vitepress.js +1 -1
- package/package.json +1 -1
- package/dist/chunk-ZM5FOUT4.js.map +0 -1
package/dist/index.d.cts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export { B as BlogAnnouncementData, a as BlogAnnouncementItem, b as BlogAuthor, c as BlogFeedConfig, d as BlogGroupBy, e as BlogIndexConfig, f as BlogLabels, g as BlogLayout, h as BlogOptions, i as BlogPostData, j as BlogScope, D as DEFAULT_LABELS, k as blogMarkdown } from './plugin-
|
|
1
|
+
export { B as BlogAnnouncementData, a as BlogAnnouncementItem, b as BlogAuthor, c as BlogFeedConfig, d as BlogGroupBy, e as BlogIndexConfig, f as BlogLabels, g as BlogLayout, h as BlogOptions, i as BlogPostData, j as BlogScope, D as DEFAULT_LABELS, k as blogMarkdown } from './plugin-kzO68Abz.cjs';
|
|
2
2
|
import 'markdown-it';
|
|
3
3
|
|
|
4
4
|
/** Marker a blog page can use to say where its list of posts goes. Without it the list is appended. */
|
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export { B as BlogAnnouncementData, a as BlogAnnouncementItem, b as BlogAuthor, c as BlogFeedConfig, d as BlogGroupBy, e as BlogIndexConfig, f as BlogLabels, g as BlogLayout, h as BlogOptions, i as BlogPostData, j as BlogScope, D as DEFAULT_LABELS, k as blogMarkdown } from './plugin-
|
|
1
|
+
export { B as BlogAnnouncementData, a as BlogAnnouncementItem, b as BlogAuthor, c as BlogFeedConfig, d as BlogGroupBy, e as BlogIndexConfig, f as BlogLabels, g as BlogLayout, h as BlogOptions, i as BlogPostData, j as BlogScope, D as DEFAULT_LABELS, k as blogMarkdown } from './plugin-kzO68Abz.js';
|
|
2
2
|
import 'markdown-it';
|
|
3
3
|
|
|
4
4
|
/** Marker a blog page can use to say where its list of posts goes. Without it the list is appended. */
|
package/dist/index.js
CHANGED
|
@@ -77,7 +77,7 @@ interface BlogOptions {
|
|
|
77
77
|
* on a site with a site URL (without one, no feeds are written). Default: `true`.
|
|
78
78
|
*/
|
|
79
79
|
rssLink?: boolean;
|
|
80
|
-
/** Words the plugin writes on pages, for translating. `{n}`, `{blog}` and `{
|
|
80
|
+
/** Words the plugin writes on pages, for translating. `{n}`, `{blog}`, `{filter}` and `{row}` are filled in. */
|
|
81
81
|
labels?: Partial<BlogLabels>;
|
|
82
82
|
}
|
|
83
83
|
interface BlogLabels {
|
|
@@ -131,6 +131,14 @@ interface BlogLabels {
|
|
|
131
131
|
removeFilter: string;
|
|
132
132
|
/** Link that clears every filter. */
|
|
133
133
|
showAll: string;
|
|
134
|
+
/** Button that shows the rest of a browse row: "+{n} more". */
|
|
135
|
+
more: string;
|
|
136
|
+
/** Button that shows a browse row's first values again. */
|
|
137
|
+
less: string;
|
|
138
|
+
/** Accessible name of the field that narrows a long browse row: "Filter {row}". */
|
|
139
|
+
filter: string;
|
|
140
|
+
/** When nothing in a browse row matches the filter field. */
|
|
141
|
+
noFilterMatches: string;
|
|
134
142
|
previous: string;
|
|
135
143
|
next: string;
|
|
136
144
|
/** Accessible name of the page links. */
|
|
@@ -173,8 +181,14 @@ interface BlogIndexConfig {
|
|
|
173
181
|
showCategory: boolean;
|
|
174
182
|
/** List every category above the posts, each one a filter. */
|
|
175
183
|
categoryList: boolean;
|
|
184
|
+
/** Categories shown before "+N more", most used first. `0` shows them all. */
|
|
185
|
+
categoryLimit: number;
|
|
176
186
|
/** List every keyword above the posts, each one a filter. */
|
|
177
187
|
tagList: boolean;
|
|
188
|
+
/** Keywords shown before "+N more", most used first. `0` shows them all. */
|
|
189
|
+
tagLimit: number;
|
|
190
|
+
/** Leave keywords used by fewer posts than this out of the browse panel. They still show on cards. */
|
|
191
|
+
tagMinCount: number;
|
|
178
192
|
/** List the years and months that have posts above the posts, each one a filter. */
|
|
179
193
|
archive: boolean;
|
|
180
194
|
/** Posts per page. `0` shows them all on one page. */
|
|
@@ -77,7 +77,7 @@ interface BlogOptions {
|
|
|
77
77
|
* on a site with a site URL (without one, no feeds are written). Default: `true`.
|
|
78
78
|
*/
|
|
79
79
|
rssLink?: boolean;
|
|
80
|
-
/** Words the plugin writes on pages, for translating. `{n}`, `{blog}` and `{
|
|
80
|
+
/** Words the plugin writes on pages, for translating. `{n}`, `{blog}`, `{filter}` and `{row}` are filled in. */
|
|
81
81
|
labels?: Partial<BlogLabels>;
|
|
82
82
|
}
|
|
83
83
|
interface BlogLabels {
|
|
@@ -131,6 +131,14 @@ interface BlogLabels {
|
|
|
131
131
|
removeFilter: string;
|
|
132
132
|
/** Link that clears every filter. */
|
|
133
133
|
showAll: string;
|
|
134
|
+
/** Button that shows the rest of a browse row: "+{n} more". */
|
|
135
|
+
more: string;
|
|
136
|
+
/** Button that shows a browse row's first values again. */
|
|
137
|
+
less: string;
|
|
138
|
+
/** Accessible name of the field that narrows a long browse row: "Filter {row}". */
|
|
139
|
+
filter: string;
|
|
140
|
+
/** When nothing in a browse row matches the filter field. */
|
|
141
|
+
noFilterMatches: string;
|
|
134
142
|
previous: string;
|
|
135
143
|
next: string;
|
|
136
144
|
/** Accessible name of the page links. */
|
|
@@ -173,8 +181,14 @@ interface BlogIndexConfig {
|
|
|
173
181
|
showCategory: boolean;
|
|
174
182
|
/** List every category above the posts, each one a filter. */
|
|
175
183
|
categoryList: boolean;
|
|
184
|
+
/** Categories shown before "+N more", most used first. `0` shows them all. */
|
|
185
|
+
categoryLimit: number;
|
|
176
186
|
/** List every keyword above the posts, each one a filter. */
|
|
177
187
|
tagList: boolean;
|
|
188
|
+
/** Keywords shown before "+N more", most used first. `0` shows them all. */
|
|
189
|
+
tagLimit: number;
|
|
190
|
+
/** Leave keywords used by fewer posts than this out of the browse panel. They still show on cards. */
|
|
191
|
+
tagMinCount: number;
|
|
178
192
|
/** List the years and months that have posts above the posts, each one a filter. */
|
|
179
193
|
archive: boolean;
|
|
180
194
|
/** Posts per page. `0` shows them all on one page. */
|
package/dist/style.css
CHANGED
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
--vp-blog-tag-bg: var(--vp-c-default-soft);
|
|
11
11
|
--vp-blog-tag-color: var(--vp-c-text-2);
|
|
12
12
|
--vp-blog-accent: var(--vp-c-brand-1);
|
|
13
|
-
--vp-blog-browse-bg:
|
|
13
|
+
--vp-blog-browse-bg: transparent;
|
|
14
14
|
/* Width of the label column in the browse panel, so every row's chips line up. */
|
|
15
15
|
--vp-blog-facet-label-width: 6.5rem;
|
|
16
16
|
--vp-blog-announcement-height: 40px;
|
|
@@ -192,7 +192,7 @@
|
|
|
192
192
|
.vp-blog-tag,
|
|
193
193
|
.vp-blog-category,
|
|
194
194
|
.vp-blog-badge,
|
|
195
|
-
.vp-blog-
|
|
195
|
+
.vp-blog-facet__chips a,
|
|
196
196
|
.vp-blog-card__tags a,
|
|
197
197
|
.vp-blog-byline__category a,
|
|
198
198
|
.vp-blog-byline__tags a {
|
|
@@ -204,11 +204,22 @@
|
|
|
204
204
|
color: var(--vp-blog-tag-color);
|
|
205
205
|
font-size: 12px;
|
|
206
206
|
font-weight: 500;
|
|
207
|
-
|
|
207
|
+
/* 24px: the smallest target WCAG 2.2 AA allows. Touch screens get more below. */
|
|
208
|
+
line-height: 24px;
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
/* Chips you tap are 32px high on touch screens. */
|
|
212
|
+
@media (pointer: coarse) {
|
|
213
|
+
.vp-blog-facet__chips a,
|
|
214
|
+
.vp-blog-card__tags a,
|
|
215
|
+
.vp-blog-byline__category a,
|
|
216
|
+
.vp-blog-byline__tags a {
|
|
217
|
+
line-height: 32px;
|
|
218
|
+
}
|
|
208
219
|
}
|
|
209
220
|
|
|
210
221
|
/* Chips are links that filter their blog. */
|
|
211
|
-
.vp-blog .vp-blog-
|
|
222
|
+
.vp-blog .vp-blog-facet__chips a,
|
|
212
223
|
.vp-blog .vp-blog-card__tags a,
|
|
213
224
|
.vp-blog-byline__category a,
|
|
214
225
|
.vp-blog-byline__tags a {
|
|
@@ -219,11 +230,11 @@
|
|
|
219
230
|
opacity 0.25s;
|
|
220
231
|
}
|
|
221
232
|
|
|
222
|
-
.vp-blog .vp-blog-
|
|
233
|
+
.vp-blog .vp-blog-facet__chips a:hover,
|
|
223
234
|
.vp-blog .vp-blog-card__tags a:hover,
|
|
224
235
|
.vp-blog-byline__category a:hover,
|
|
225
236
|
.vp-blog-byline__tags a:hover,
|
|
226
|
-
.vp-blog .vp-blog-
|
|
237
|
+
.vp-blog .vp-blog-facet__chips a.is-active,
|
|
227
238
|
.vp-blog .vp-blog-card__tags a.is-active {
|
|
228
239
|
background: var(--vp-c-brand-soft);
|
|
229
240
|
color: var(--vp-blog-accent);
|
|
@@ -311,24 +322,27 @@
|
|
|
311
322
|
|
|
312
323
|
/*
|
|
313
324
|
* The browse panel: one row each for categories, keywords and years, and the
|
|
314
|
-
* months of the year in view below the years.
|
|
315
|
-
*
|
|
325
|
+
* months of the year in view below the years. A flat toolbar between two
|
|
326
|
+
* rules, so it reads as a tool rather than another post. On wide screens the
|
|
327
|
+
* labels sit in a column of their own and chips wrap; on narrow ones each row
|
|
328
|
+
* is a single line that scrolls sideways.
|
|
316
329
|
*/
|
|
317
330
|
.vp-blog-browse {
|
|
318
331
|
display: flex;
|
|
319
332
|
flex-direction: column;
|
|
320
|
-
gap:
|
|
333
|
+
gap: 8px;
|
|
321
334
|
margin: 16px 0;
|
|
322
|
-
padding:
|
|
323
|
-
border: 1px solid var(--vp-
|
|
324
|
-
border-
|
|
335
|
+
padding: 12px 0;
|
|
336
|
+
border-top: 1px solid var(--vp-c-divider);
|
|
337
|
+
border-bottom: 1px solid var(--vp-c-divider);
|
|
325
338
|
background: var(--vp-blog-browse-bg);
|
|
326
339
|
}
|
|
327
340
|
|
|
328
341
|
.vp-blog-facet {
|
|
329
342
|
display: grid;
|
|
330
|
-
|
|
331
|
-
|
|
343
|
+
/* Label, chips, then "+N more" and the "Subscribe" link when the row has them. */
|
|
344
|
+
grid-template-columns: var(--vp-blog-facet-label-width) minmax(0, 1fr) auto auto;
|
|
345
|
+
gap: 4px 12px;
|
|
332
346
|
align-items: baseline;
|
|
333
347
|
}
|
|
334
348
|
|
|
@@ -336,19 +350,33 @@
|
|
|
336
350
|
color: var(--vp-blog-meta-color);
|
|
337
351
|
font-size: 13px;
|
|
338
352
|
font-weight: 600;
|
|
339
|
-
line-height:
|
|
353
|
+
line-height: 28px;
|
|
340
354
|
}
|
|
341
355
|
|
|
342
|
-
/* A year's months
|
|
356
|
+
/* A year's months, under the years: their label is the year. */
|
|
343
357
|
.vp-blog-facet--month .vp-blog-facet__label {
|
|
344
358
|
font-variant-numeric: tabular-nums;
|
|
345
359
|
font-weight: 500;
|
|
346
360
|
}
|
|
347
361
|
|
|
362
|
+
.vp-blog-facet__chips {
|
|
363
|
+
min-width: 0;
|
|
364
|
+
}
|
|
365
|
+
|
|
348
366
|
.vp-blog-facet__chips p {
|
|
367
|
+
display: flex;
|
|
368
|
+
flex-wrap: wrap;
|
|
369
|
+
gap: 4px 6px;
|
|
370
|
+
align-items: center;
|
|
349
371
|
margin: 0;
|
|
350
372
|
}
|
|
351
373
|
|
|
374
|
+
.vp-blog .vp-blog-facet__chips a {
|
|
375
|
+
flex: none;
|
|
376
|
+
margin: 0;
|
|
377
|
+
white-space: nowrap;
|
|
378
|
+
}
|
|
379
|
+
|
|
352
380
|
/* The post count in a chip: a small counter badge inside it. */
|
|
353
381
|
.vp-blog-facet__count {
|
|
354
382
|
display: inline-block;
|
|
@@ -369,29 +397,125 @@
|
|
|
369
397
|
color 0.25s;
|
|
370
398
|
}
|
|
371
399
|
|
|
372
|
-
.vp-blog-
|
|
373
|
-
.vp-blog-
|
|
400
|
+
.vp-blog-facet__chips a:hover .vp-blog-facet__count,
|
|
401
|
+
.vp-blog-facet__chips a.is-active .vp-blog-facet__count {
|
|
374
402
|
background: var(--vp-blog-accent);
|
|
375
403
|
/* The page background, so the number stays readable on the accent in light and dark mode. */
|
|
376
404
|
color: var(--vp-c-bg);
|
|
377
405
|
}
|
|
378
406
|
|
|
379
407
|
/* A chip that would show no posts with the other filters kept. */
|
|
380
|
-
.vp-blog .vp-blog-
|
|
408
|
+
.vp-blog .vp-blog-facet__chips a.is-empty {
|
|
381
409
|
opacity: 0.45;
|
|
382
410
|
}
|
|
383
411
|
|
|
384
|
-
.vp-blog .vp-blog-
|
|
412
|
+
.vp-blog .vp-blog-facet__chips a.is-empty:hover {
|
|
385
413
|
opacity: 0.8;
|
|
386
414
|
}
|
|
387
415
|
|
|
416
|
+
/* "+N more" and "Show fewer": a quiet text button at the end of the row's first line. */
|
|
417
|
+
.vp-blog-facet__more {
|
|
418
|
+
justify-self: start;
|
|
419
|
+
padding: 0 6px;
|
|
420
|
+
border-radius: 6px;
|
|
421
|
+
color: var(--vp-blog-accent);
|
|
422
|
+
font-size: 12px;
|
|
423
|
+
font-weight: 600;
|
|
424
|
+
line-height: 28px;
|
|
425
|
+
white-space: nowrap;
|
|
426
|
+
cursor: pointer;
|
|
427
|
+
}
|
|
428
|
+
|
|
429
|
+
.vp-blog-facet__more:hover {
|
|
430
|
+
background: var(--vp-c-brand-soft);
|
|
431
|
+
}
|
|
432
|
+
|
|
433
|
+
/* The field that narrows a long open row, above its chips. */
|
|
434
|
+
.vp-blog-facet__filter {
|
|
435
|
+
display: block;
|
|
436
|
+
box-sizing: border-box;
|
|
437
|
+
width: min(100%, 18rem);
|
|
438
|
+
margin: 0 0 8px;
|
|
439
|
+
padding: 4px 10px;
|
|
440
|
+
border: 1px solid var(--vp-c-divider);
|
|
441
|
+
border-radius: 8px;
|
|
442
|
+
background: var(--vp-c-bg);
|
|
443
|
+
color: var(--vp-c-text-1);
|
|
444
|
+
font-size: 13px;
|
|
445
|
+
line-height: 20px;
|
|
446
|
+
}
|
|
447
|
+
|
|
448
|
+
.vp-blog-facet__filter:focus {
|
|
449
|
+
border-color: var(--vp-blog-accent);
|
|
450
|
+
outline: none;
|
|
451
|
+
}
|
|
452
|
+
|
|
453
|
+
.vp-blog-facet__empty {
|
|
454
|
+
margin: 0;
|
|
455
|
+
color: var(--vp-blog-meta-color);
|
|
456
|
+
font-size: 13px;
|
|
457
|
+
}
|
|
458
|
+
|
|
459
|
+
/* The "Subscribe" link at the end of the first row. */
|
|
460
|
+
.vp-blog-facet__aside p {
|
|
461
|
+
margin: 0;
|
|
462
|
+
white-space: nowrap;
|
|
463
|
+
}
|
|
464
|
+
|
|
465
|
+
@media (pointer: coarse) {
|
|
466
|
+
.vp-blog-facet__more {
|
|
467
|
+
line-height: 32px;
|
|
468
|
+
}
|
|
469
|
+
|
|
470
|
+
.vp-blog-facet__label {
|
|
471
|
+
line-height: 32px;
|
|
472
|
+
}
|
|
473
|
+
}
|
|
474
|
+
|
|
388
475
|
@media (max-width: 639px) {
|
|
389
476
|
.vp-blog-facet {
|
|
390
|
-
grid-template-columns: minmax(0, 1fr);
|
|
477
|
+
grid-template-columns: auto minmax(0, 1fr) auto auto;
|
|
478
|
+
gap: 4px 8px;
|
|
479
|
+
align-items: center;
|
|
391
480
|
}
|
|
392
481
|
|
|
393
482
|
.vp-blog-facet__label {
|
|
394
|
-
|
|
483
|
+
font-size: 12px;
|
|
484
|
+
}
|
|
485
|
+
|
|
486
|
+
/* One line per row, scrolled sideways, its end fading while there is more. */
|
|
487
|
+
.vp-blog-facet:not(.is-open) .vp-blog-facet__chips {
|
|
488
|
+
overflow-x: auto;
|
|
489
|
+
overscroll-behavior-x: contain;
|
|
490
|
+
scrollbar-width: none;
|
|
491
|
+
}
|
|
492
|
+
|
|
493
|
+
.vp-blog-facet:not(.is-open) .vp-blog-facet__chips::-webkit-scrollbar {
|
|
494
|
+
display: none;
|
|
495
|
+
}
|
|
496
|
+
|
|
497
|
+
.vp-blog-facet:not(.is-open) .vp-blog-facet__chips p {
|
|
498
|
+
flex-wrap: nowrap;
|
|
499
|
+
}
|
|
500
|
+
|
|
501
|
+
.vp-blog-facet.is-scrollable:not(.is-open) .vp-blog-facet__chips {
|
|
502
|
+
mask-image: linear-gradient(to right, #000 calc(100% - 32px), transparent);
|
|
503
|
+
}
|
|
504
|
+
|
|
505
|
+
/* An open row wraps under its label, at full width. */
|
|
506
|
+
.vp-blog-facet.is-open .vp-blog-facet__chips {
|
|
507
|
+
grid-column: 1 / -1;
|
|
508
|
+
grid-row: 2;
|
|
509
|
+
}
|
|
510
|
+
|
|
511
|
+
/* The RSS icon alone, its words kept for screen readers. */
|
|
512
|
+
.vp-blog-facet__aside .vp-blog-rss__text {
|
|
513
|
+
position: absolute;
|
|
514
|
+
width: 1px;
|
|
515
|
+
height: 1px;
|
|
516
|
+
overflow: hidden;
|
|
517
|
+
clip-path: inset(50%);
|
|
518
|
+
white-space: nowrap;
|
|
395
519
|
}
|
|
396
520
|
}
|
|
397
521
|
|
package/dist/vitepress.cjs
CHANGED
|
@@ -160,6 +160,10 @@ var DEFAULT_LABELS = {
|
|
|
160
160
|
noMatches: "No posts match these filters.",
|
|
161
161
|
removeFilter: "Remove filter: {filter}",
|
|
162
162
|
showAll: "Show all posts",
|
|
163
|
+
more: "+{n} more",
|
|
164
|
+
less: "Show fewer",
|
|
165
|
+
filter: "Filter {row}",
|
|
166
|
+
noFilterMatches: "Nothing matches.",
|
|
163
167
|
previous: "Previous",
|
|
164
168
|
next: "Next",
|
|
165
169
|
pages: "Pages",
|
|
@@ -347,6 +351,8 @@ var FENCED_CODE = /^[ \t]*(`{3,}|~{3,})[^\n]*\n[\s\S]*?(?:^[ \t]*\1[`~]*[ \t]*$|
|
|
|
347
351
|
var HEADING_1 = /^ {0,3}#[ \t]+(.*?)(?:[ \t]+#+)?[ \t]*$/m;
|
|
348
352
|
var TAG_SYNTAX = /\(\(<?tag([|/])[^|/)\r\n]*(?:\1[^|/)\r\n]*){0,2}\)\)/g;
|
|
349
353
|
var MAX_SUMMARY_LENGTH = 200;
|
|
354
|
+
var DEFAULT_CATEGORY_LIMIT = 8;
|
|
355
|
+
var DEFAULT_TAG_LIMIT = 12;
|
|
350
356
|
function readFrontmatter(raw) {
|
|
351
357
|
const source = raw.replace(/^/, "");
|
|
352
358
|
const match = FRONTMATTER.exec(source);
|
|
@@ -517,7 +523,10 @@ function resolveIndexConfig(data, relativePath, defaults = {}) {
|
|
|
517
523
|
showTags: options.showTags !== false,
|
|
518
524
|
showCategory: options.showCategory !== false,
|
|
519
525
|
categoryList: options.categoryList !== false,
|
|
526
|
+
categoryLimit: toCount(options.categoryLimit, DEFAULT_CATEGORY_LIMIT),
|
|
520
527
|
tagList: options.tagList !== false,
|
|
528
|
+
tagLimit: toCount(options.tagLimit, DEFAULT_TAG_LIMIT),
|
|
529
|
+
tagMinCount: toCount(options.tagMinCount, 1),
|
|
521
530
|
archive: options.archive !== false,
|
|
522
531
|
pageSize: toCount(options.pageSize, toCount(defaults.pageSize, 10)),
|
|
523
532
|
pinLimit: toCount(options.pinLimit ?? options.stickyLimit, toCount(defaults.pinLimit ?? defaults.stickyLimit, 0)),
|
|
@@ -648,7 +657,8 @@ function renderRssLink(index, context, show = index.index.rssLink) {
|
|
|
648
657
|
if (!show || !context.feeds || !index.index.feed) return "";
|
|
649
658
|
const title = fill(context.labels.rssFeed, { blog: index.title }).replace(/"/g, """);
|
|
650
659
|
const url = toMarkdownUrl(`/${toFeedPath(index)}`);
|
|
651
|
-
|
|
660
|
+
const text = `<span class="vp-blog-rss__text">${escapeMarkdown(context.labels.subscribe)}</span>`;
|
|
661
|
+
return `<span class="vp-blog-rss">[${RSS_ICON} ${text}](${url} "${title}")</span>`;
|
|
652
662
|
}
|
|
653
663
|
function fill(template, values) {
|
|
654
664
|
return template.replace(/\{(\w+)\}/g, (match, key) => values[key] ?? match);
|
|
@@ -843,60 +853,73 @@ function renderChip(name, count, url, title = "") {
|
|
|
843
853
|
const tooltip = title ? ` "${title.replace(/"/g, """)}"` : "";
|
|
844
854
|
return `[<span class="vp-blog-facet__name">${escapeMarkdown(name)}</span> <span class="vp-blog-facet__count">${count}</span>](${url}${tooltip})`;
|
|
845
855
|
}
|
|
846
|
-
function renderFacet(
|
|
856
|
+
function renderFacet(row) {
|
|
857
|
+
const { facet, label, chips, ariaLabel = label, limit = 0, attributes = "", aside = "" } = row;
|
|
858
|
+
const limited = limit && chips.length > limit ? ` data-limit="${limit}"` : "";
|
|
847
859
|
return [
|
|
848
|
-
`<div class="vp-blog-facet vp-blog-facet--${facet}" role="group" aria-label="${escapeHtml(ariaLabel)}" data-vp-blog-facet="${facet}"${attributes}>`,
|
|
860
|
+
`<div class="vp-blog-facet vp-blog-facet--${facet}" role="group" aria-label="${escapeHtml(ariaLabel)}" data-vp-blog-facet="${facet}"${limited}${attributes}>`,
|
|
849
861
|
`<span class="vp-blog-facet__label" aria-hidden="true">${escapeTemplateText(label)}</span>`,
|
|
850
862
|
'<div class="vp-blog-facet__chips">',
|
|
851
863
|
"",
|
|
852
864
|
chips.join(" "),
|
|
853
865
|
"",
|
|
854
866
|
"</div>",
|
|
867
|
+
...block("vp-blog-facet__aside", aside),
|
|
855
868
|
"</div>"
|
|
856
869
|
];
|
|
857
870
|
}
|
|
871
|
+
function canNarrow(values, total) {
|
|
872
|
+
return values.length > 1 || values.length === 1 && values[0].count < total;
|
|
873
|
+
}
|
|
874
|
+
function byUse(a, b) {
|
|
875
|
+
return b.count - a.count || a.value.localeCompare(b.value, void 0, { sensitivity: "base" });
|
|
876
|
+
}
|
|
858
877
|
function renderBrowse(posts, index, context) {
|
|
859
878
|
const { labels } = context;
|
|
860
879
|
const { locale, timeZone } = context.dates;
|
|
880
|
+
const { categoryList, categoryLimit, tagList, tagLimit, tagMinCount, archive: showArchive } = index.index;
|
|
861
881
|
const blog = index.routePath;
|
|
862
882
|
const rows = [];
|
|
863
|
-
const categories =
|
|
864
|
-
if (categories.length) {
|
|
883
|
+
const categories = categoryList ? collectCategories(posts).sort(byUse) : [];
|
|
884
|
+
if (canNarrow(categories, posts.length)) {
|
|
865
885
|
const chips = categories.map(({ value, count }) => renderChip(value, count, toFilterUrl(blog, "category", value)));
|
|
866
|
-
rows.push(
|
|
886
|
+
rows.push({ facet: "category", label: labels.categories, chips, limit: categoryLimit });
|
|
867
887
|
}
|
|
868
|
-
const tags =
|
|
869
|
-
if (tags.length) {
|
|
870
|
-
const chips = tags.map(({
|
|
871
|
-
rows.push(
|
|
888
|
+
const tags = tagList ? collectTags(posts).map(({ tag, count }) => ({ value: tag, count })).filter(({ count }) => count >= tagMinCount).sort(byUse) : [];
|
|
889
|
+
if (canNarrow(tags, posts.length)) {
|
|
890
|
+
const chips = tags.map(({ value, count }) => renderChip(value, count, toFilterUrl(blog, "tag", value)));
|
|
891
|
+
rows.push({ facet: "tag", label: labels.tags, chips, limit: tagLimit });
|
|
872
892
|
}
|
|
873
|
-
const archive =
|
|
874
|
-
|
|
893
|
+
const archive = showArchive ? collectArchive(posts, timeZone) : [];
|
|
894
|
+
const monthChips = (months) => months.map(
|
|
895
|
+
({ value, count }) => renderChip(
|
|
896
|
+
formatMonth(value, locale, { month: "short" }),
|
|
897
|
+
count,
|
|
898
|
+
toFilterUrl(blog, "month", value),
|
|
899
|
+
formatMonth(value, locale, { month: "long", year: "numeric" })
|
|
900
|
+
)
|
|
901
|
+
);
|
|
902
|
+
if (archive.length === 1 && canNarrow(archive[0].months, posts.length)) {
|
|
903
|
+
const [year] = archive;
|
|
904
|
+
const ariaLabel = `${labels.archive} ${year.value}`;
|
|
905
|
+
const attributes = ` data-year="${year.value}"`;
|
|
906
|
+
rows.push({ facet: "month", label: labels.archive, chips: monthChips(year.months), ariaLabel, attributes });
|
|
907
|
+
} else if (archive.length > 1) {
|
|
875
908
|
const years = archive.map(({ value, count }) => renderChip(value, count, toFilterUrl(blog, "year", value)));
|
|
876
|
-
rows.push(
|
|
909
|
+
rows.push({ facet: "year", label: labels.archive, chips: years });
|
|
877
910
|
for (const year of archive) {
|
|
878
|
-
const
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
count,
|
|
882
|
-
toFilterUrl(blog, "month", value),
|
|
883
|
-
formatMonth(value, locale, { month: "long", year: "numeric" })
|
|
884
|
-
)
|
|
885
|
-
);
|
|
886
|
-
const shown = archive.length === 1 ? "" : " hidden";
|
|
887
|
-
rows.push(
|
|
888
|
-
...renderFacet(
|
|
889
|
-
"month",
|
|
890
|
-
year.value,
|
|
891
|
-
months,
|
|
892
|
-
`${labels.archive} ${year.value}`,
|
|
893
|
-
` data-year="${year.value}"${shown}`
|
|
894
|
-
)
|
|
895
|
-
);
|
|
911
|
+
const ariaLabel = `${labels.archive} ${year.value}`;
|
|
912
|
+
const attributes = ` data-year="${year.value}" hidden`;
|
|
913
|
+
rows.push({ facet: "month", label: year.value, chips: monthChips(year.months), ariaLabel, attributes });
|
|
896
914
|
}
|
|
897
915
|
}
|
|
898
916
|
if (rows.length === 0) return [];
|
|
899
|
-
|
|
917
|
+
rows[0].aside = renderRssLink(index, context);
|
|
918
|
+
return [
|
|
919
|
+
`<nav class="vp-blog-browse" aria-label="${escapeHtml(labels.browse)}">`,
|
|
920
|
+
...rows.flatMap(renderFacet),
|
|
921
|
+
"</nav>"
|
|
922
|
+
];
|
|
900
923
|
}
|
|
901
924
|
function renderClientAttributes(index, context) {
|
|
902
925
|
const { labels } = context;
|
|
@@ -914,7 +937,11 @@ function renderClientAttributes(index, context) {
|
|
|
914
937
|
"data-label-post-count": labels.postCount,
|
|
915
938
|
"data-label-post-count-one": labels.postCountOne,
|
|
916
939
|
"data-label-no-matches": labels.noMatches,
|
|
917
|
-
"data-label-remove-filter": labels.removeFilter
|
|
940
|
+
"data-label-remove-filter": labels.removeFilter,
|
|
941
|
+
"data-label-more": labels.more,
|
|
942
|
+
"data-label-less": labels.less,
|
|
943
|
+
"data-label-filter": labels.filter,
|
|
944
|
+
"data-label-no-filter-matches": labels.noFilterMatches
|
|
918
945
|
};
|
|
919
946
|
return Object.entries(attributes).map(([name, value]) => `${name}="${escapeHtml(value)}"`).join(" ");
|
|
920
947
|
}
|
|
@@ -922,10 +949,10 @@ function renderPostList(pinned, rest, index, context) {
|
|
|
922
949
|
const all = [...pinned, ...rest];
|
|
923
950
|
if (all.length === 0) return `<p class="vp-blog-empty">${escapeTemplateText(context.labels.noPosts)}</p>
|
|
924
951
|
`;
|
|
952
|
+
const browse = renderBrowse(all, index, context);
|
|
925
953
|
const lines = [
|
|
926
954
|
`<div class="vp-blog" data-vp-blog ${renderClientAttributes(index, context)}>`,
|
|
927
|
-
...block("vp-blog-subscribe", renderRssLink(index, context)),
|
|
928
|
-
...renderBrowse(all, index, context),
|
|
955
|
+
...browse.length ? browse : block("vp-blog-subscribe", renderRssLink(index, context)),
|
|
929
956
|
'<div class="vp-blog-filter" data-vp-blog-filter role="status" hidden></div>'
|
|
930
957
|
];
|
|
931
958
|
if (pinned.length)
|