@binarynoir/vitepress-blog 0.3.0 → 0.4.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 +144 -83
- package/dist/{chunk-LYTJBMVK.js → chunk-ZM5FOUT4.js} +188 -74
- package/dist/chunk-ZM5FOUT4.js.map +1 -0
- package/dist/client.cjs +160 -56
- package/dist/client.cjs.map +1 -1
- package/dist/client.d.cts +26 -14
- package/dist/client.d.ts +26 -14
- package/dist/client.js +159 -56
- package/dist/client.js.map +1 -1
- package/dist/index.cjs +185 -71
- 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-Bb4rRwO8.d.cts → plugin-DUTUA_t4.d.cts} +46 -22
- package/dist/{plugin-Bb4rRwO8.d.ts → plugin-DUTUA_t4.d.ts} +46 -22
- package/dist/style.css +157 -25
- package/dist/vitepress.cjs +188 -74
- 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 +2 -2
- package/dist/vitepress.js.map +1 -1
- package/package.json +1 -1
- package/dist/chunk-LYTJBMVK.js.map +0 -1
|
@@ -30,6 +30,11 @@ function hasAnyTag(post, tags) {
|
|
|
30
30
|
const wanted = new Set(tags.map((tag) => tag.toLowerCase()));
|
|
31
31
|
return post.post.tags.some((tag) => wanted.has(tag.toLowerCase()));
|
|
32
32
|
}
|
|
33
|
+
function inAnyCategory(post, categories) {
|
|
34
|
+
if (categories.length === 0) return true;
|
|
35
|
+
const category = post.post.category.toLowerCase();
|
|
36
|
+
return !!category && categories.some((wanted) => wanted.toLowerCase() === category);
|
|
37
|
+
}
|
|
33
38
|
function blogCoversPost(index, post, sections) {
|
|
34
39
|
if (index.index.scope === "section") return isInFolders(post.relativePath, index.index.folders);
|
|
35
40
|
if (!isInFolders(post.relativePath, index.index.folders)) return false;
|
|
@@ -43,22 +48,22 @@ function compareDates(a, b) {
|
|
|
43
48
|
function compareByDate(a, b) {
|
|
44
49
|
return compareDates(a.post.date, b.post.date) || a.post.title.localeCompare(b.post.title);
|
|
45
50
|
}
|
|
46
|
-
function
|
|
47
|
-
const
|
|
48
|
-
const pinned = new Set(limit ?
|
|
51
|
+
function pinPosts(posts, limit) {
|
|
52
|
+
const candidates = posts.filter((post) => post.post.pinned);
|
|
53
|
+
const pinned = new Set(limit ? candidates.slice(0, limit) : candidates);
|
|
49
54
|
return { pinned: [...pinned], rest: posts.filter((post) => !pinned.has(post)) };
|
|
50
55
|
}
|
|
51
56
|
function listBlogPosts(pages, index, options) {
|
|
52
57
|
const sections = pages.filter(isIndex).filter((page) => page.index.scope === "section");
|
|
53
|
-
let posts = pages.filter(isPost).filter((post) => options.drafts || !post.post.draft).filter((post) => blogCoversPost(index, post, sections) && hasAnyTag(post, index.index.tags)).sort(compareByDate);
|
|
54
|
-
if (options.
|
|
55
|
-
const { pinned, rest } =
|
|
58
|
+
let posts = pages.filter(isPost).filter((post) => options.drafts || !post.post.draft).filter((post) => blogCoversPost(index, post, sections) && hasAnyTag(post, index.index.tags)).filter((post) => inAnyCategory(post, index.index.categories)).sort(compareByDate);
|
|
59
|
+
if (options.pinnedFirst) {
|
|
60
|
+
const { pinned, rest } = pinPosts(posts, index.index.pinLimit);
|
|
56
61
|
posts = [...pinned, ...rest];
|
|
57
62
|
}
|
|
58
63
|
return options.applyLimit && index.index.limit ? posts.slice(0, index.index.limit) : posts;
|
|
59
64
|
}
|
|
60
65
|
function findHomeBlog(pages, post, drafts) {
|
|
61
|
-
const listing = pages.filter(isIndex).filter((index) => listBlogPosts(pages, index, { drafts,
|
|
66
|
+
const listing = pages.filter(isIndex).filter((index) => listBlogPosts(pages, index, { drafts, pinnedFirst: false, applyLimit: false }).includes(post));
|
|
62
67
|
const sections = listing.filter((index) => index.index.scope === "section");
|
|
63
68
|
if (sections.length) return deepestFirst(sections, post.relativePath)[0];
|
|
64
69
|
return listing[0] ?? null;
|
|
@@ -77,7 +82,7 @@ function findBlogForPage(pages, relativePath) {
|
|
|
77
82
|
}
|
|
78
83
|
function findBlogsListing(pages, post) {
|
|
79
84
|
return pages.filter(isIndex).filter(
|
|
80
|
-
(index) => listBlogPosts(pages, index, { drafts: false,
|
|
85
|
+
(index) => listBlogPosts(pages, index, { drafts: false, pinnedFirst: false, applyLimit: false }).includes(post)
|
|
81
86
|
);
|
|
82
87
|
}
|
|
83
88
|
function listAnnouncements(pages, drafts) {
|
|
@@ -86,7 +91,7 @@ function listAnnouncements(pages, drafts) {
|
|
|
86
91
|
function findAnnouncementBlog(pages, announcements, drafts) {
|
|
87
92
|
if (announcements.length === 0) return null;
|
|
88
93
|
const listingAll = pages.filter(isIndex).filter((index) => {
|
|
89
|
-
const listed = listBlogPosts(pages, index, { drafts,
|
|
94
|
+
const listed = listBlogPosts(pages, index, { drafts, pinnedFirst: false, applyLimit: false });
|
|
90
95
|
return announcements.every((post) => listed.includes(post));
|
|
91
96
|
});
|
|
92
97
|
return listingAll.find((index) => index.index.scope === "site") ?? listingAll[0] ?? findHomeBlog(pages, announcements[0], drafts);
|
|
@@ -197,18 +202,24 @@ var DEFAULT_LABELS = {
|
|
|
197
202
|
older: "Older post",
|
|
198
203
|
allPosts: "All posts in {blog}",
|
|
199
204
|
draft: "Draft",
|
|
200
|
-
|
|
205
|
+
pinned: "Pinned",
|
|
201
206
|
announcement: "Announcement",
|
|
202
207
|
announcements: "Announcements",
|
|
203
|
-
noAnnouncements: "No announcements.",
|
|
204
208
|
announcementCount: "{n} announcements",
|
|
205
209
|
dismiss: "Dismiss",
|
|
206
210
|
noPosts: "No posts yet.",
|
|
207
211
|
undated: "Undated",
|
|
212
|
+
browse: "Browse posts",
|
|
213
|
+
categories: "Categories",
|
|
208
214
|
tags: "Keywords",
|
|
209
|
-
|
|
215
|
+
archive: "Archive",
|
|
216
|
+
category: "Category",
|
|
217
|
+
tag: "Keyword",
|
|
218
|
+
postCount: "{n} posts",
|
|
219
|
+
postCountOne: "{n} post",
|
|
220
|
+
noMatches: "No posts match these filters.",
|
|
221
|
+
removeFilter: "Remove filter: {filter}",
|
|
210
222
|
showAll: "Show all posts",
|
|
211
|
-
noTagged: "No posts tagged {tag}.",
|
|
212
223
|
previous: "Previous",
|
|
213
224
|
next: "Next",
|
|
214
225
|
pages: "Pages",
|
|
@@ -314,6 +325,13 @@ function toDateTimeAttribute({ date, hasTime }, timeZone) {
|
|
|
314
325
|
function yearIn(date, timeZone) {
|
|
315
326
|
return Number(toZonedIsoDate(date, timeZone).slice(0, 4));
|
|
316
327
|
}
|
|
328
|
+
function monthIn(date, timeZone) {
|
|
329
|
+
return toZonedIsoDate(date, timeZone).slice(0, 7);
|
|
330
|
+
}
|
|
331
|
+
function formatMonth(month, locale, format) {
|
|
332
|
+
const [year, number] = month.split("-").map(Number);
|
|
333
|
+
return new Intl.DateTimeFormat(locale, { timeZone: "UTC", ...format }).format(Date.UTC(year, number - 1, 1, 12));
|
|
334
|
+
}
|
|
317
335
|
|
|
318
336
|
// src/render.ts
|
|
319
337
|
var BLOG_POSTS_PLACEHOLDER = "<!-- blog-posts -->";
|
|
@@ -369,27 +387,33 @@ function renderAuthors(authors, context) {
|
|
|
369
387
|
function renderBadge(kind, context) {
|
|
370
388
|
return `<span class="vp-blog-badge vp-blog-badge--${kind}">${escapeTemplateText(context.labels[kind])}</span>`;
|
|
371
389
|
}
|
|
372
|
-
function
|
|
373
|
-
const
|
|
390
|
+
function toFilterUrl(blogRoutePath, param, value) {
|
|
391
|
+
const encoded = encodeURIComponent(value.toLowerCase()).replace(/[()]/g, (c) => c === "(" ? "%28" : "%29");
|
|
374
392
|
const page = blogRoutePath.replace(/(^|\/)index\.md$/, "$1");
|
|
375
|
-
return `${toMarkdownUrl(`/${page}`)}
|
|
393
|
+
return `${toMarkdownUrl(`/${page}`)}?${param}=${encoded}`;
|
|
394
|
+
}
|
|
395
|
+
function renderFilterLink(text, param, blogRoutePath, className) {
|
|
396
|
+
return blogRoutePath ? `[${escapeMarkdown(text)}](${toFilterUrl(blogRoutePath, param, text)})` : `<span class="${className}">${escapeTemplateText(text)}</span>`;
|
|
376
397
|
}
|
|
377
398
|
function renderTags(tags, blogRoutePath) {
|
|
378
|
-
return tags.map(
|
|
379
|
-
(tag) => blogRoutePath ? `[${escapeMarkdown(tag)}](${toTagUrl(blogRoutePath, tag)})` : `<span class="vp-blog-tag">${escapeTemplateText(tag)}</span>`
|
|
380
|
-
).join(" ");
|
|
399
|
+
return tags.map((tag) => renderFilterLink(tag, "tag", blogRoutePath, "vp-blog-tag")).join(" ");
|
|
381
400
|
}
|
|
382
401
|
function toTagsAttribute(post) {
|
|
383
402
|
return escapeHtml(post.post.tags.map((tag) => tag.toLowerCase()).join("|"));
|
|
384
403
|
}
|
|
385
|
-
function toItemAttributes(post) {
|
|
386
|
-
|
|
404
|
+
function toItemAttributes(post, context) {
|
|
405
|
+
const { category, date, announcement } = post.post;
|
|
406
|
+
const attributes = [`data-vp-blog-item data-tags="${toTagsAttribute(post)}"`];
|
|
407
|
+
if (category) attributes.push(`data-category="${escapeHtml(category.toLowerCase())}"`);
|
|
408
|
+
if (date) attributes.push(`data-month="${monthIn(date, context.dates.timeZone)}"`);
|
|
409
|
+
if (announcement) attributes.push("data-announcement");
|
|
410
|
+
return attributes.join(" ");
|
|
387
411
|
}
|
|
388
412
|
function renderBadges(post, context) {
|
|
389
|
-
const { draft,
|
|
413
|
+
const { draft, pinned, announcement } = post.post;
|
|
390
414
|
return [
|
|
391
415
|
draft && renderBadge("draft", context),
|
|
392
|
-
|
|
416
|
+
pinned && renderBadge("pinned", context),
|
|
393
417
|
announcement && renderBadge("announcement", context)
|
|
394
418
|
].filter(Boolean).join(" ");
|
|
395
419
|
}
|
|
@@ -424,7 +448,7 @@ function renderCard(post, context, index) {
|
|
|
424
448
|
const link = `/${post.routePath}`;
|
|
425
449
|
const image = toImageSource(post, context.pageDirectory);
|
|
426
450
|
const modifiers = [
|
|
427
|
-
post.post.
|
|
451
|
+
post.post.pinned && "pinned",
|
|
428
452
|
post.post.draft && "draft",
|
|
429
453
|
post.post.announcement && "announcement",
|
|
430
454
|
image && "with-image",
|
|
@@ -432,9 +456,10 @@ function renderCard(post, context, index) {
|
|
|
432
456
|
].filter(Boolean).map((modifier) => ` vp-blog-card--${modifier}`).join("");
|
|
433
457
|
const alt = escapeMarkdown(post.post.imageAlt);
|
|
434
458
|
return [
|
|
435
|
-
`<article class="vp-blog-card${modifiers}"${imageStyle(post)} ${toItemAttributes(post)}>`,
|
|
459
|
+
`<article class="vp-blog-card${modifiers}"${imageStyle(post)} ${toItemAttributes(post, context)}>`,
|
|
436
460
|
...image ? block("vp-blog-card__image", `[})](${toMarkdownUrl(link)})`) : [],
|
|
437
461
|
'<div class="vp-blog-card__body">',
|
|
462
|
+
...index.index.showCategory && post.post.category ? block("vp-blog-card__category", renderFilterLink(post.post.category, "category", index.routePath, "")) : [],
|
|
438
463
|
...block("vp-blog-card__title", toPageLink(post.post.title, post.routePath)),
|
|
439
464
|
...block("vp-blog-card__meta", renderMeta(post, context, { authors: true, updated: false, badges: true })),
|
|
440
465
|
...block("vp-blog-card__summary", escapeMarkdown(post.post.summary)),
|
|
@@ -446,7 +471,7 @@ function renderCard(post, context, index) {
|
|
|
446
471
|
function renderCompactItem(post, context) {
|
|
447
472
|
const date = post.post.date ? `${renderTime(post.post.date, post.post.dateHasTime, context)} ` : "";
|
|
448
473
|
const badges = renderBadges(post, context);
|
|
449
|
-
const marker = `<span hidden ${toItemAttributes(post)}></span>`;
|
|
474
|
+
const marker = `<span hidden ${toItemAttributes(post, context)}></span>`;
|
|
450
475
|
return `- ${marker}${date}${toPageLink(post.post.title, post.routePath)}${badges ? ` ${badges}` : ""}`;
|
|
451
476
|
}
|
|
452
477
|
function renderGroup(posts, index, context) {
|
|
@@ -466,18 +491,23 @@ function renderGroup(posts, index, context) {
|
|
|
466
491
|
"</div>"
|
|
467
492
|
];
|
|
468
493
|
}
|
|
469
|
-
function
|
|
470
|
-
const
|
|
494
|
+
function renderGroups(posts, index, context) {
|
|
495
|
+
const { groupBy } = index.index;
|
|
496
|
+
if (!groupBy) return renderGroup(posts, index, context);
|
|
497
|
+
const { timeZone, locale } = context.dates;
|
|
498
|
+
const groups = /* @__PURE__ */ new Map();
|
|
471
499
|
for (const post of posts) {
|
|
472
|
-
const
|
|
473
|
-
|
|
500
|
+
const { date } = post.post;
|
|
501
|
+
const key = !date ? "" : groupBy === "year" ? String(yearIn(date, timeZone)) : monthIn(date, timeZone);
|
|
502
|
+
groups.set(key, [...groups.get(key) ?? [], post]);
|
|
474
503
|
}
|
|
475
504
|
const lines = [];
|
|
476
|
-
for (const [
|
|
505
|
+
for (const [key, group] of groups) {
|
|
506
|
+
const heading = !key ? context.labels.undated : groupBy === "year" ? key : formatMonth(key, locale, { month: "long", year: "numeric" });
|
|
477
507
|
lines.push(
|
|
478
|
-
|
|
508
|
+
`<section class="vp-blog-group vp-blog-${groupBy}">`,
|
|
479
509
|
"",
|
|
480
|
-
`## ${escapeMarkdown(
|
|
510
|
+
`## ${escapeMarkdown(heading)}`,
|
|
481
511
|
"",
|
|
482
512
|
...renderGroup(group, index, context),
|
|
483
513
|
"",
|
|
@@ -486,44 +516,114 @@ function renderYears(posts, index, context) {
|
|
|
486
516
|
}
|
|
487
517
|
return lines;
|
|
488
518
|
}
|
|
489
|
-
function
|
|
490
|
-
const
|
|
519
|
+
function collectValues(posts, pick) {
|
|
520
|
+
const values = /* @__PURE__ */ new Map();
|
|
491
521
|
for (const post of posts) {
|
|
492
|
-
for (const
|
|
493
|
-
const entry =
|
|
522
|
+
for (const value of new Set(pick(post))) {
|
|
523
|
+
const entry = values.get(value.toLowerCase()) ?? { value, count: 0 };
|
|
494
524
|
entry.count++;
|
|
495
|
-
|
|
525
|
+
values.set(value.toLowerCase(), entry);
|
|
496
526
|
}
|
|
497
527
|
}
|
|
498
|
-
return [...
|
|
528
|
+
return [...values.values()].sort((a, b) => a.value.localeCompare(b.value, void 0, { sensitivity: "base" }));
|
|
499
529
|
}
|
|
500
|
-
function
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
530
|
+
function collectTags(posts) {
|
|
531
|
+
return collectValues(posts, (post) => post.post.tags).map(({ value, count }) => ({ tag: value, count }));
|
|
532
|
+
}
|
|
533
|
+
function collectCategories(posts) {
|
|
534
|
+
return collectValues(posts, (post) => post.post.category ? [post.post.category] : []);
|
|
535
|
+
}
|
|
536
|
+
function collectArchive(posts, timeZone) {
|
|
537
|
+
const years = /* @__PURE__ */ new Map();
|
|
538
|
+
for (const post of posts) {
|
|
539
|
+
if (!post.post.date) continue;
|
|
540
|
+
const month = monthIn(post.post.date, timeZone);
|
|
541
|
+
const year = years.get(month.slice(0, 4)) ?? { value: month.slice(0, 4), count: 0, months: [] };
|
|
542
|
+
year.count++;
|
|
543
|
+
const entry = year.months.find((candidate) => candidate.value === month);
|
|
544
|
+
if (entry) entry.count++;
|
|
545
|
+
else year.months.push({ value: month, count: 1 });
|
|
546
|
+
years.set(year.value, year);
|
|
547
|
+
}
|
|
548
|
+
const newestFirst = (a, b) => b.value.localeCompare(a.value);
|
|
549
|
+
return [...years.values()].sort(newestFirst).map((year) => ({ ...year, months: [...year.months].sort(newestFirst) }));
|
|
550
|
+
}
|
|
551
|
+
function renderChip(name, count, url, title = "") {
|
|
552
|
+
const tooltip = title ? ` "${title.replace(/"/g, """)}"` : "";
|
|
553
|
+
return `[<span class="vp-blog-facet__name">${escapeMarkdown(name)}</span> <span class="vp-blog-facet__count">${count}</span>](${url}${tooltip})`;
|
|
554
|
+
}
|
|
555
|
+
function renderFacet(facet, label, chips, ariaLabel = label, attributes = "") {
|
|
507
556
|
return [
|
|
508
|
-
`<
|
|
557
|
+
`<div class="vp-blog-facet vp-blog-facet--${facet}" role="group" aria-label="${escapeHtml(ariaLabel)}" data-vp-blog-facet="${facet}"${attributes}>`,
|
|
558
|
+
`<span class="vp-blog-facet__label" aria-hidden="true">${escapeTemplateText(label)}</span>`,
|
|
559
|
+
'<div class="vp-blog-facet__chips">',
|
|
509
560
|
"",
|
|
510
|
-
|
|
561
|
+
chips.join(" "),
|
|
511
562
|
"",
|
|
512
|
-
"</
|
|
563
|
+
"</div>",
|
|
564
|
+
"</div>"
|
|
513
565
|
];
|
|
514
566
|
}
|
|
567
|
+
function renderBrowse(posts, index, context) {
|
|
568
|
+
const { labels } = context;
|
|
569
|
+
const { locale, timeZone } = context.dates;
|
|
570
|
+
const blog = index.routePath;
|
|
571
|
+
const rows = [];
|
|
572
|
+
const categories = index.index.categoryList ? collectCategories(posts) : [];
|
|
573
|
+
if (categories.length) {
|
|
574
|
+
const chips = categories.map(({ value, count }) => renderChip(value, count, toFilterUrl(blog, "category", value)));
|
|
575
|
+
rows.push(...renderFacet("category", labels.categories, chips));
|
|
576
|
+
}
|
|
577
|
+
const tags = index.index.tagList ? collectTags(posts) : [];
|
|
578
|
+
if (tags.length) {
|
|
579
|
+
const chips = tags.map(({ tag, count }) => renderChip(tag, count, toFilterUrl(blog, "tag", tag)));
|
|
580
|
+
rows.push(...renderFacet("tag", labels.tags, chips));
|
|
581
|
+
}
|
|
582
|
+
const archive = index.index.archive ? collectArchive(posts, timeZone) : [];
|
|
583
|
+
if (archive.reduce((months, year) => months + year.months.length, 0) > 1) {
|
|
584
|
+
const years = archive.map(({ value, count }) => renderChip(value, count, toFilterUrl(blog, "year", value)));
|
|
585
|
+
rows.push(...renderFacet("year", labels.archive, years));
|
|
586
|
+
for (const year of archive) {
|
|
587
|
+
const months = year.months.map(
|
|
588
|
+
({ value, count }) => renderChip(
|
|
589
|
+
formatMonth(value, locale, { month: "short" }),
|
|
590
|
+
count,
|
|
591
|
+
toFilterUrl(blog, "month", value),
|
|
592
|
+
formatMonth(value, locale, { month: "long", year: "numeric" })
|
|
593
|
+
)
|
|
594
|
+
);
|
|
595
|
+
const shown = archive.length === 1 ? "" : " hidden";
|
|
596
|
+
rows.push(
|
|
597
|
+
...renderFacet(
|
|
598
|
+
"month",
|
|
599
|
+
year.value,
|
|
600
|
+
months,
|
|
601
|
+
`${labels.archive} ${year.value}`,
|
|
602
|
+
` data-year="${year.value}"${shown}`
|
|
603
|
+
)
|
|
604
|
+
);
|
|
605
|
+
}
|
|
606
|
+
}
|
|
607
|
+
if (rows.length === 0) return [];
|
|
608
|
+
return [`<nav class="vp-blog-browse" aria-label="${escapeHtml(labels.browse)}">`, ...rows, "</nav>"];
|
|
609
|
+
}
|
|
515
610
|
function renderClientAttributes(index, context) {
|
|
516
611
|
const { labels } = context;
|
|
517
612
|
const attributes = {
|
|
518
613
|
"data-page-size": String(index.index.pageSize),
|
|
519
|
-
"
|
|
614
|
+
// For writing a `?month=` filter's name: "October 2026".
|
|
615
|
+
"data-locale": context.locale,
|
|
520
616
|
"data-label-show-all": labels.showAll,
|
|
521
|
-
"data-label-no-tagged": labels.noTagged,
|
|
522
617
|
"data-label-previous": labels.previous,
|
|
523
618
|
"data-label-next": labels.next,
|
|
524
619
|
"data-label-pages": labels.pages,
|
|
525
620
|
"data-label-announcements": labels.announcements,
|
|
526
|
-
"data-label-
|
|
621
|
+
"data-label-category": labels.category,
|
|
622
|
+
"data-label-tag": labels.tag,
|
|
623
|
+
"data-label-post-count": labels.postCount,
|
|
624
|
+
"data-label-post-count-one": labels.postCountOne,
|
|
625
|
+
"data-label-no-matches": labels.noMatches,
|
|
626
|
+
"data-label-remove-filter": labels.removeFilter
|
|
527
627
|
};
|
|
528
628
|
return Object.entries(attributes).map(([name, value]) => `${name}="${escapeHtml(value)}"`).join(" ");
|
|
529
629
|
}
|
|
@@ -534,17 +634,16 @@ function renderPostList(pinned, rest, index, context) {
|
|
|
534
634
|
const lines = [
|
|
535
635
|
`<div class="vp-blog" data-vp-blog ${renderClientAttributes(index, context)}>`,
|
|
536
636
|
...block("vp-blog-subscribe", renderRssLink(index, context)),
|
|
537
|
-
...
|
|
538
|
-
'<div class="vp-blog-filter" data-vp-blog-filter hidden></div>'
|
|
637
|
+
...renderBrowse(all, index, context),
|
|
638
|
+
'<div class="vp-blog-filter" data-vp-blog-filter role="status" hidden></div>'
|
|
539
639
|
];
|
|
540
640
|
if (pinned.length)
|
|
541
641
|
lines.push(
|
|
542
|
-
'<section class="vp-blog-
|
|
642
|
+
'<section class="vp-blog-pinned" data-vp-blog-pinned>',
|
|
543
643
|
...renderGroup(pinned, index, context),
|
|
544
644
|
"</section>"
|
|
545
645
|
);
|
|
546
|
-
if (rest.length)
|
|
547
|
-
lines.push(...index.index.groupByYear ? renderYears(rest, index, context) : renderGroup(rest, index, context));
|
|
646
|
+
if (rest.length) lines.push(...renderGroups(rest, index, context));
|
|
548
647
|
lines.push(`<nav class="vp-blog-pagination" data-vp-blog-pagination hidden></nav>`, "</div>");
|
|
549
648
|
return `${lines.join("\n")}
|
|
550
649
|
`;
|
|
@@ -553,8 +652,12 @@ function renderPostHeader(post, context, show, blogRoutePath = null) {
|
|
|
553
652
|
const lines = [];
|
|
554
653
|
if (show.byline) {
|
|
555
654
|
const meta = renderMeta(post, context, { authors: true, updated: true, badges: true });
|
|
556
|
-
const
|
|
557
|
-
|
|
655
|
+
const { category, tags } = post.post;
|
|
656
|
+
const chips = [
|
|
657
|
+
category && `<span class="vp-blog-byline__category">${renderFilterLink(category, "category", blogRoutePath, "vp-blog-category")}</span>`,
|
|
658
|
+
tags.length && `<span class="vp-blog-byline__tags">${renderTags(tags, blogRoutePath)}</span>`
|
|
659
|
+
].filter(Boolean).join(" ");
|
|
660
|
+
lines.push(...block("vp-blog-byline", [meta, chips].filter(Boolean).join("\n\n")));
|
|
558
661
|
}
|
|
559
662
|
if (show.cover && post.post.image) {
|
|
560
663
|
const image = /^[./@~]/.test(post.post.image) || isExternalUrl(post.post.image) ? post.post.image : `./${post.post.image}`;
|
|
@@ -705,7 +808,8 @@ function resolvePostData(data, content, fallbackTitle, options = {}) {
|
|
|
705
808
|
tags: toStringList(pick("tags")),
|
|
706
809
|
category: toText(pick("category")),
|
|
707
810
|
scope: toScope(post.scope),
|
|
708
|
-
|
|
811
|
+
// `sticky` is this setting's old name.
|
|
812
|
+
pinned: (post.pinned ?? post.sticky) === true,
|
|
709
813
|
draft: post.draft === true,
|
|
710
814
|
announcement: post.announcement === true || !!announcementText,
|
|
711
815
|
announcementText,
|
|
@@ -718,6 +822,9 @@ function resolvePostData(data, content, fallbackTitle, options = {}) {
|
|
|
718
822
|
function toLayout(value) {
|
|
719
823
|
return value === "grid" || value === "compact" ? value : "list";
|
|
720
824
|
}
|
|
825
|
+
function toGroupBy(value) {
|
|
826
|
+
return value === "year" || value === "month" ? value : "";
|
|
827
|
+
}
|
|
721
828
|
function defaultFeedPath(relativePath) {
|
|
722
829
|
const name = path3.posix.basename(relativePath, ".md");
|
|
723
830
|
return name === "index" ? "feed.xml" : `${name}-feed.xml`;
|
|
@@ -751,13 +858,17 @@ function resolveIndexConfig(data, relativePath, defaults = {}) {
|
|
|
751
858
|
scope,
|
|
752
859
|
folders: folders.length ? resolveFolders(folders, relativePath) : scope === "section" ? [ownFolder] : [],
|
|
753
860
|
tags: toStringList(options.tags),
|
|
861
|
+
categories: toStringList(options.categories),
|
|
754
862
|
limit: typeof options.limit === "number" && options.limit > 0 ? Math.floor(options.limit) : 0,
|
|
755
863
|
layout: toLayout(options.layout),
|
|
756
|
-
|
|
864
|
+
groupBy: toGroupBy(options.groupBy),
|
|
757
865
|
showTags: options.showTags !== false,
|
|
866
|
+
showCategory: options.showCategory !== false,
|
|
867
|
+
categoryList: options.categoryList !== false,
|
|
758
868
|
tagList: options.tagList !== false,
|
|
869
|
+
archive: options.archive !== false,
|
|
759
870
|
pageSize: toCount(options.pageSize, toCount(defaults.pageSize, 10)),
|
|
760
|
-
|
|
871
|
+
pinLimit: toCount(options.pinLimit ?? options.stickyLimit, toCount(defaults.pinLimit ?? defaults.stickyLimit, 0)),
|
|
761
872
|
rssLink: typeof options.rssLink === "boolean" ? options.rssLink : defaults.rssLink ?? true,
|
|
762
873
|
feed: toFeed(options.feed, relativePath)
|
|
763
874
|
};
|
|
@@ -827,7 +938,7 @@ function toOptionsKey(options) {
|
|
|
827
938
|
options.wordsPerMinute,
|
|
828
939
|
options.stripTags,
|
|
829
940
|
options.pageSize,
|
|
830
|
-
options.stickyLimit,
|
|
941
|
+
options.pinLimit ?? options.stickyLimit,
|
|
831
942
|
options.rssLink,
|
|
832
943
|
options.timeZone
|
|
833
944
|
]);
|
|
@@ -916,10 +1027,13 @@ function resolveWidgetConfig(body) {
|
|
|
916
1027
|
config: {
|
|
917
1028
|
blog: typeof data.blog === "string" ? data.blog.trim() : "",
|
|
918
1029
|
limit: toCount2(data.limit) ?? DEFAULT_LIMIT,
|
|
919
|
-
stickyLimit
|
|
1030
|
+
// `stickyLimit` is this setting's old name.
|
|
1031
|
+
pinLimit: toCount2(data.pinLimit ?? data.stickyLimit),
|
|
920
1032
|
layout,
|
|
921
1033
|
showTags: typeof data.showTags === "boolean" ? data.showTags : void 0,
|
|
1034
|
+
showCategory: typeof data.showCategory === "boolean" ? data.showCategory : void 0,
|
|
922
1035
|
tags: toStringList(data.tags),
|
|
1036
|
+
categories: toStringList(data.categories),
|
|
923
1037
|
more: data.more === false ? null : typeof data.more === "string" && data.more.trim() ? data.more.trim() : "",
|
|
924
1038
|
rssLink: typeof data.rssLink === "boolean" ? data.rssLink : void 0
|
|
925
1039
|
},
|
|
@@ -935,19 +1049,19 @@ function renderWidget(body, environment) {
|
|
|
935
1049
|
warn(config.blog ? `no blog page found at "${config.blog}"` : 'no blog covers this page: name one with "blog:"');
|
|
936
1050
|
return "";
|
|
937
1051
|
}
|
|
938
|
-
const
|
|
939
|
-
const
|
|
940
|
-
|
|
941
|
-
(post) => wanted.size === 0 || post.post.tags.some((tag) => wanted.has(tag.toLowerCase()))
|
|
1052
|
+
const pinLimit = config.pinLimit ?? blog.index.pinLimit;
|
|
1053
|
+
const posts = listBlogPosts(pages, blog, { drafts, pinnedFirst: false, applyLimit: false }).filter(
|
|
1054
|
+
(post) => hasAnyTag(post, config.tags) && inAnyCategory(post, config.categories)
|
|
942
1055
|
);
|
|
943
|
-
const { pinned, rest } =
|
|
1056
|
+
const { pinned, rest } = pinPosts(posts, pinLimit);
|
|
944
1057
|
const shown = [...pinned, ...rest].slice(0, config.limit || void 0);
|
|
945
1058
|
const view = {
|
|
946
1059
|
...blog,
|
|
947
1060
|
index: {
|
|
948
1061
|
...blog.index,
|
|
949
1062
|
layout: config.layout ?? blog.index.layout,
|
|
950
|
-
showTags: config.showTags ?? blog.index.showTags
|
|
1063
|
+
showTags: config.showTags ?? blog.index.showTags,
|
|
1064
|
+
showCategory: config.showCategory ?? blog.index.showCategory
|
|
951
1065
|
}
|
|
952
1066
|
};
|
|
953
1067
|
const lines = [`<div class="vp-blog-widget">`];
|
|
@@ -1021,8 +1135,8 @@ function hasFeeds(options) {
|
|
|
1021
1135
|
}
|
|
1022
1136
|
function withPostList(source, page, pages, options) {
|
|
1023
1137
|
if (!isIndex(page)) return source;
|
|
1024
|
-
const posts = listBlogPosts(pages, page, { drafts: options.drafts ?? false,
|
|
1025
|
-
const { pinned, rest } =
|
|
1138
|
+
const posts = listBlogPosts(pages, page, { drafts: options.drafts ?? false, pinnedFirst: true, applyLimit: true });
|
|
1139
|
+
const { pinned, rest } = pinPosts(posts, page.index.pinLimit);
|
|
1026
1140
|
const context = createRenderContext(options, path6.dirname(page.absolutePath), hasFeeds(options));
|
|
1027
1141
|
const generated = renderPostList(pinned, rest, page, context);
|
|
1028
1142
|
return source.includes(BLOG_POSTS_PLACEHOLDER) ? source.replace(BLOG_POSTS_PLACEHOLDER, () => `
|
|
@@ -1045,7 +1159,7 @@ function withPostDecorations(source, page, pages, options) {
|
|
|
1045
1159
|
let result = header ? insertAfterTitle(source, header) : source;
|
|
1046
1160
|
if (page.post.postNav ?? options.postNav ?? true) {
|
|
1047
1161
|
if (blog) {
|
|
1048
|
-
const posts = listBlogPosts(pages, blog, { drafts,
|
|
1162
|
+
const posts = listBlogPosts(pages, blog, { drafts, pinnedFirst: false, applyLimit: false });
|
|
1049
1163
|
result = `${result.replace(/\s*$/, "")}
|
|
1050
1164
|
|
|
1051
1165
|
${renderPostNav(page, posts, blog, context)}
|
|
@@ -1114,4 +1228,4 @@ export {
|
|
|
1114
1228
|
hasWidget,
|
|
1115
1229
|
blogMarkdown
|
|
1116
1230
|
};
|
|
1117
|
-
//# sourceMappingURL=chunk-
|
|
1231
|
+
//# sourceMappingURL=chunk-ZM5FOUT4.js.map
|