@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/README.md
CHANGED
|
@@ -267,24 +267,27 @@ Notes from Team A.
|
|
|
267
267
|
|
|
268
268
|
The list goes where `<!-- blog-posts -->` is, or after the page's content.
|
|
269
269
|
|
|
270
|
-
| Key
|
|
271
|
-
|
|
|
272
|
-
| `scope`
|
|
273
|
-
| `folders`
|
|
274
|
-
| `tags`
|
|
275
|
-
| `categories`
|
|
276
|
-
| `limit`
|
|
277
|
-
| `layout`
|
|
278
|
-
| `groupBy`
|
|
279
|
-
| `showTags`
|
|
280
|
-
| `showCategory`
|
|
281
|
-
| `categoryList`
|
|
282
|
-
| `
|
|
283
|
-
| `
|
|
284
|
-
| `
|
|
285
|
-
| `
|
|
286
|
-
| `
|
|
287
|
-
| `
|
|
270
|
+
| Key | Default | What it does |
|
|
271
|
+
| --------------- | ----------------------------- | ----------------------------------------------------------------------------------------------- |
|
|
272
|
+
| `scope` | `section` | `site` makes this the main blog. See [Scopes](#scopes). |
|
|
273
|
+
| `folders` | the page's folder | Folders to list posts from, relative to the source directory; `./` and `../` are page-relative. |
|
|
274
|
+
| `tags` | all | Only list posts with at least one of these tags. |
|
|
275
|
+
| `categories` | all | Only list posts in one of these categories. |
|
|
276
|
+
| `limit` | all | Most posts to list. The feed has its own limit. |
|
|
277
|
+
| `layout` | `list` | `list` (image beside text), `grid` (cards) or `compact` (dates and titles). |
|
|
278
|
+
| `groupBy` | none | `year` or `month` puts a heading ("2026", "October 2026") above each year's or month's posts. |
|
|
279
|
+
| `showTags` | `true` | `false` hides tag chips on cards. |
|
|
280
|
+
| `showCategory` | `true` | `false` hides the category above each card's title. |
|
|
281
|
+
| `categoryList` | `true` | A row of categories in the browse panel, each with its count. `false` leaves it out. |
|
|
282
|
+
| `categoryLimit` | `8` | Categories shown before "+N more", most used first. `0` shows them all. |
|
|
283
|
+
| `tagList` | `true` | A row of keywords in the browse panel, each with its count. `false` leaves it out. |
|
|
284
|
+
| `tagLimit` | `12` | Keywords shown before "+N more", most used first. `0` shows them all. |
|
|
285
|
+
| `tagMinCount` | `1` | Leave keywords used by fewer posts out of the browse panel. They still show on cards. |
|
|
286
|
+
| `archive` | `true` | Rows of years, and each year's months, in the browse panel. `false` leaves them out. |
|
|
287
|
+
| `pageSize` | `10` (the `pageSize` option) | Posts per page. `0` shows them all on one page. |
|
|
288
|
+
| `pinLimit` | all (the `pinLimit` option) | Most pinned posts kept at the top. Extra ones take their place by date. |
|
|
289
|
+
| `rssLink` | `true` (the `rssLink` option) | A "Subscribe" link with the RSS icon to this blog's feed. `false` leaves it out. |
|
|
290
|
+
| `feed` | on | `false` turns the feed off, or `{ title, description, limit, path }` to set it up. |
|
|
288
291
|
|
|
289
292
|
### Pinned posts
|
|
290
293
|
|
|
@@ -328,7 +331,8 @@ Filters combine: `?category=engineering&tag=api&year=2026` shows the
|
|
|
328
331
|
engineering posts tagged `api` from 2026. Pages count the matching posts only.
|
|
329
332
|
|
|
330
333
|
**The browse panel** above the posts has a row each for categories, keywords
|
|
331
|
-
and the archive, each chip with its post count
|
|
334
|
+
and the archive, each chip with its post count. It is a flat toolbar between
|
|
335
|
+
two rules, with the blog's "Subscribe" link at the end of its first row.
|
|
332
336
|
|
|
333
337
|
- **Chips combine.** A chip adds its filter to the ones in view; another chip
|
|
334
338
|
in the same row replaces it, and clicking the active chip takes it off again.
|
|
@@ -338,8 +342,18 @@ and the archive, each chip with its post count:
|
|
|
338
342
|
- **Years open into months.** Choosing a year shows a row of its months below
|
|
339
343
|
the years (with only one year, its months always show). A month keeps its
|
|
340
344
|
year active, and clicking it again steps back out to the whole year.
|
|
341
|
-
-
|
|
342
|
-
|
|
345
|
+
- **It stays short with many values.** Categories and keywords are ranked by
|
|
346
|
+
how many posts use them, and a row shows its first `categoryLimit` (8) or
|
|
347
|
+
`tagLimit` (12), then "+N more". That opens the full list alphabetically,
|
|
348
|
+
and a row of more than 30 values also gets a field to narrow it. An active
|
|
349
|
+
chip always shows. `tagMinCount: 2` leaves out keywords used only once.
|
|
350
|
+
- **One line per row on phones.** On screens narrower than 640px, each row is
|
|
351
|
+
a single line that scrolls sideways, its end fading while there is more.
|
|
352
|
+
Chips are 32px high on touch screens.
|
|
353
|
+
- **Rows only appear when they can narrow the posts.** No categories, or one
|
|
354
|
+
category that every post is in, means no category row. The archive needs
|
|
355
|
+
posts from more than one month, and with only one year, it is that year's
|
|
356
|
+
months alone.
|
|
343
357
|
|
|
344
358
|
**The active filters** show above the posts while any filter is on: how many
|
|
345
359
|
posts match ("4 posts", or "No posts match these filters."), a chip for each
|
|
@@ -552,6 +566,10 @@ withBlog(config, {
|
|
|
552
566
|
noMatches: 'Keine Beiträge für diese Filter.',
|
|
553
567
|
removeFilter: 'Filter entfernen: {filter}',
|
|
554
568
|
showAll: 'Alle Beiträge zeigen',
|
|
569
|
+
more: '+{n} weitere',
|
|
570
|
+
less: 'Weniger zeigen',
|
|
571
|
+
filter: '{row} filtern',
|
|
572
|
+
noFilterMatches: 'Keine Treffer.',
|
|
555
573
|
previous: 'Zurück',
|
|
556
574
|
next: 'Weiter',
|
|
557
575
|
pages: 'Seiten',
|
|
@@ -575,7 +593,7 @@ mode. Override these to restyle it without new rules:
|
|
|
575
593
|
| `--vp-blog-tag-bg` | `var(--vp-c-default-soft)` |
|
|
576
594
|
| `--vp-blog-tag-color` | `var(--vp-c-text-2)` |
|
|
577
595
|
| `--vp-blog-accent` | `var(--vp-c-brand-1)` |
|
|
578
|
-
| `--vp-blog-browse-bg` | `
|
|
596
|
+
| `--vp-blog-browse-bg` | `transparent` |
|
|
579
597
|
| `--vp-blog-facet-label-width` | `6.5rem` |
|
|
580
598
|
| `--vp-blog-announcement-height` | `40px` |
|
|
581
599
|
| `--vp-blog-announcement-bg` | `var(--vp-button-brand-bg)` |
|
|
@@ -220,6 +220,10 @@ var DEFAULT_LABELS = {
|
|
|
220
220
|
noMatches: "No posts match these filters.",
|
|
221
221
|
removeFilter: "Remove filter: {filter}",
|
|
222
222
|
showAll: "Show all posts",
|
|
223
|
+
more: "+{n} more",
|
|
224
|
+
less: "Show fewer",
|
|
225
|
+
filter: "Filter {row}",
|
|
226
|
+
noFilterMatches: "Nothing matches.",
|
|
223
227
|
previous: "Previous",
|
|
224
228
|
next: "Next",
|
|
225
229
|
pages: "Pages",
|
|
@@ -357,7 +361,8 @@ function renderRssLink(index, context, show = index.index.rssLink) {
|
|
|
357
361
|
if (!show || !context.feeds || !index.index.feed) return "";
|
|
358
362
|
const title = fill(context.labels.rssFeed, { blog: index.title }).replace(/"/g, """);
|
|
359
363
|
const url = toMarkdownUrl(`/${toFeedPath(index)}`);
|
|
360
|
-
|
|
364
|
+
const text = `<span class="vp-blog-rss__text">${escapeMarkdown(context.labels.subscribe)}</span>`;
|
|
365
|
+
return `<span class="vp-blog-rss">[${RSS_ICON} ${text}](${url} "${title}")</span>`;
|
|
361
366
|
}
|
|
362
367
|
function fill(template, values) {
|
|
363
368
|
return template.replace(/\{(\w+)\}/g, (match, key) => values[key] ?? match);
|
|
@@ -552,60 +557,73 @@ function renderChip(name, count, url, title = "") {
|
|
|
552
557
|
const tooltip = title ? ` "${title.replace(/"/g, """)}"` : "";
|
|
553
558
|
return `[<span class="vp-blog-facet__name">${escapeMarkdown(name)}</span> <span class="vp-blog-facet__count">${count}</span>](${url}${tooltip})`;
|
|
554
559
|
}
|
|
555
|
-
function renderFacet(
|
|
560
|
+
function renderFacet(row) {
|
|
561
|
+
const { facet, label, chips, ariaLabel = label, limit = 0, attributes = "", aside = "" } = row;
|
|
562
|
+
const limited = limit && chips.length > limit ? ` data-limit="${limit}"` : "";
|
|
556
563
|
return [
|
|
557
|
-
`<div class="vp-blog-facet vp-blog-facet--${facet}" role="group" aria-label="${escapeHtml(ariaLabel)}" data-vp-blog-facet="${facet}"${attributes}>`,
|
|
564
|
+
`<div class="vp-blog-facet vp-blog-facet--${facet}" role="group" aria-label="${escapeHtml(ariaLabel)}" data-vp-blog-facet="${facet}"${limited}${attributes}>`,
|
|
558
565
|
`<span class="vp-blog-facet__label" aria-hidden="true">${escapeTemplateText(label)}</span>`,
|
|
559
566
|
'<div class="vp-blog-facet__chips">',
|
|
560
567
|
"",
|
|
561
568
|
chips.join(" "),
|
|
562
569
|
"",
|
|
563
570
|
"</div>",
|
|
571
|
+
...block("vp-blog-facet__aside", aside),
|
|
564
572
|
"</div>"
|
|
565
573
|
];
|
|
566
574
|
}
|
|
575
|
+
function canNarrow(values, total) {
|
|
576
|
+
return values.length > 1 || values.length === 1 && values[0].count < total;
|
|
577
|
+
}
|
|
578
|
+
function byUse(a, b) {
|
|
579
|
+
return b.count - a.count || a.value.localeCompare(b.value, void 0, { sensitivity: "base" });
|
|
580
|
+
}
|
|
567
581
|
function renderBrowse(posts, index, context) {
|
|
568
582
|
const { labels } = context;
|
|
569
583
|
const { locale, timeZone } = context.dates;
|
|
584
|
+
const { categoryList, categoryLimit, tagList, tagLimit, tagMinCount, archive: showArchive } = index.index;
|
|
570
585
|
const blog = index.routePath;
|
|
571
586
|
const rows = [];
|
|
572
|
-
const categories =
|
|
573
|
-
if (categories.length) {
|
|
587
|
+
const categories = categoryList ? collectCategories(posts).sort(byUse) : [];
|
|
588
|
+
if (canNarrow(categories, posts.length)) {
|
|
574
589
|
const chips = categories.map(({ value, count }) => renderChip(value, count, toFilterUrl(blog, "category", value)));
|
|
575
|
-
rows.push(
|
|
590
|
+
rows.push({ facet: "category", label: labels.categories, chips, limit: categoryLimit });
|
|
576
591
|
}
|
|
577
|
-
const tags =
|
|
578
|
-
if (tags.length) {
|
|
579
|
-
const chips = tags.map(({
|
|
580
|
-
rows.push(
|
|
592
|
+
const tags = tagList ? collectTags(posts).map(({ tag, count }) => ({ value: tag, count })).filter(({ count }) => count >= tagMinCount).sort(byUse) : [];
|
|
593
|
+
if (canNarrow(tags, posts.length)) {
|
|
594
|
+
const chips = tags.map(({ value, count }) => renderChip(value, count, toFilterUrl(blog, "tag", value)));
|
|
595
|
+
rows.push({ facet: "tag", label: labels.tags, chips, limit: tagLimit });
|
|
581
596
|
}
|
|
582
|
-
const archive =
|
|
583
|
-
|
|
597
|
+
const archive = showArchive ? collectArchive(posts, timeZone) : [];
|
|
598
|
+
const monthChips = (months) => months.map(
|
|
599
|
+
({ value, count }) => renderChip(
|
|
600
|
+
formatMonth(value, locale, { month: "short" }),
|
|
601
|
+
count,
|
|
602
|
+
toFilterUrl(blog, "month", value),
|
|
603
|
+
formatMonth(value, locale, { month: "long", year: "numeric" })
|
|
604
|
+
)
|
|
605
|
+
);
|
|
606
|
+
if (archive.length === 1 && canNarrow(archive[0].months, posts.length)) {
|
|
607
|
+
const [year] = archive;
|
|
608
|
+
const ariaLabel = `${labels.archive} ${year.value}`;
|
|
609
|
+
const attributes = ` data-year="${year.value}"`;
|
|
610
|
+
rows.push({ facet: "month", label: labels.archive, chips: monthChips(year.months), ariaLabel, attributes });
|
|
611
|
+
} else if (archive.length > 1) {
|
|
584
612
|
const years = archive.map(({ value, count }) => renderChip(value, count, toFilterUrl(blog, "year", value)));
|
|
585
|
-
rows.push(
|
|
613
|
+
rows.push({ facet: "year", label: labels.archive, chips: years });
|
|
586
614
|
for (const year of archive) {
|
|
587
|
-
const
|
|
588
|
-
|
|
589
|
-
|
|
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
|
-
);
|
|
615
|
+
const ariaLabel = `${labels.archive} ${year.value}`;
|
|
616
|
+
const attributes = ` data-year="${year.value}" hidden`;
|
|
617
|
+
rows.push({ facet: "month", label: year.value, chips: monthChips(year.months), ariaLabel, attributes });
|
|
605
618
|
}
|
|
606
619
|
}
|
|
607
620
|
if (rows.length === 0) return [];
|
|
608
|
-
|
|
621
|
+
rows[0].aside = renderRssLink(index, context);
|
|
622
|
+
return [
|
|
623
|
+
`<nav class="vp-blog-browse" aria-label="${escapeHtml(labels.browse)}">`,
|
|
624
|
+
...rows.flatMap(renderFacet),
|
|
625
|
+
"</nav>"
|
|
626
|
+
];
|
|
609
627
|
}
|
|
610
628
|
function renderClientAttributes(index, context) {
|
|
611
629
|
const { labels } = context;
|
|
@@ -623,7 +641,11 @@ function renderClientAttributes(index, context) {
|
|
|
623
641
|
"data-label-post-count": labels.postCount,
|
|
624
642
|
"data-label-post-count-one": labels.postCountOne,
|
|
625
643
|
"data-label-no-matches": labels.noMatches,
|
|
626
|
-
"data-label-remove-filter": labels.removeFilter
|
|
644
|
+
"data-label-remove-filter": labels.removeFilter,
|
|
645
|
+
"data-label-more": labels.more,
|
|
646
|
+
"data-label-less": labels.less,
|
|
647
|
+
"data-label-filter": labels.filter,
|
|
648
|
+
"data-label-no-filter-matches": labels.noFilterMatches
|
|
627
649
|
};
|
|
628
650
|
return Object.entries(attributes).map(([name, value]) => `${name}="${escapeHtml(value)}"`).join(" ");
|
|
629
651
|
}
|
|
@@ -631,10 +653,10 @@ function renderPostList(pinned, rest, index, context) {
|
|
|
631
653
|
const all = [...pinned, ...rest];
|
|
632
654
|
if (all.length === 0) return `<p class="vp-blog-empty">${escapeTemplateText(context.labels.noPosts)}</p>
|
|
633
655
|
`;
|
|
656
|
+
const browse = renderBrowse(all, index, context);
|
|
634
657
|
const lines = [
|
|
635
658
|
`<div class="vp-blog" data-vp-blog ${renderClientAttributes(index, context)}>`,
|
|
636
|
-
...block("vp-blog-subscribe", renderRssLink(index, context)),
|
|
637
|
-
...renderBrowse(all, index, context),
|
|
659
|
+
...browse.length ? browse : block("vp-blog-subscribe", renderRssLink(index, context)),
|
|
638
660
|
'<div class="vp-blog-filter" data-vp-blog-filter role="status" hidden></div>'
|
|
639
661
|
];
|
|
640
662
|
if (pinned.length)
|
|
@@ -695,6 +717,8 @@ var FENCED_CODE = /^[ \t]*(`{3,}|~{3,})[^\n]*\n[\s\S]*?(?:^[ \t]*\1[`~]*[ \t]*$|
|
|
|
695
717
|
var HEADING_1 = /^ {0,3}#[ \t]+(.*?)(?:[ \t]+#+)?[ \t]*$/m;
|
|
696
718
|
var TAG_SYNTAX = /\(\(<?tag([|/])[^|/)\r\n]*(?:\1[^|/)\r\n]*){0,2}\)\)/g;
|
|
697
719
|
var MAX_SUMMARY_LENGTH = 200;
|
|
720
|
+
var DEFAULT_CATEGORY_LIMIT = 8;
|
|
721
|
+
var DEFAULT_TAG_LIMIT = 12;
|
|
698
722
|
function readFrontmatter(raw) {
|
|
699
723
|
const source = raw.replace(/^/, "");
|
|
700
724
|
const match = FRONTMATTER.exec(source);
|
|
@@ -865,7 +889,10 @@ function resolveIndexConfig(data, relativePath, defaults = {}) {
|
|
|
865
889
|
showTags: options.showTags !== false,
|
|
866
890
|
showCategory: options.showCategory !== false,
|
|
867
891
|
categoryList: options.categoryList !== false,
|
|
892
|
+
categoryLimit: toCount(options.categoryLimit, DEFAULT_CATEGORY_LIMIT),
|
|
868
893
|
tagList: options.tagList !== false,
|
|
894
|
+
tagLimit: toCount(options.tagLimit, DEFAULT_TAG_LIMIT),
|
|
895
|
+
tagMinCount: toCount(options.tagMinCount, 1),
|
|
869
896
|
archive: options.archive !== false,
|
|
870
897
|
pageSize: toCount(options.pageSize, toCount(defaults.pageSize, 10)),
|
|
871
898
|
pinLimit: toCount(options.pinLimit ?? options.stickyLimit, toCount(defaults.pinLimit ?? defaults.stickyLimit, 0)),
|
|
@@ -1228,4 +1255,4 @@ export {
|
|
|
1228
1255
|
hasWidget,
|
|
1229
1256
|
blogMarkdown
|
|
1230
1257
|
};
|
|
1231
|
-
//# sourceMappingURL=chunk-
|
|
1258
|
+
//# sourceMappingURL=chunk-FPFH7ORO.js.map
|