@binarynoir/vitepress-blog 0.2.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 +238 -88
- package/dist/chunk-42Z6H7IN.js +52 -0
- package/dist/chunk-42Z6H7IN.js.map +1 -0
- package/dist/{chunk-PWNWSYI4.js → chunk-ZM5FOUT4.js} +229 -106
- package/dist/chunk-ZM5FOUT4.js.map +1 -0
- package/dist/client.cjs +280 -64
- package/dist/client.cjs.map +1 -1
- package/dist/client.d.cts +56 -13
- package/dist/client.d.ts +56 -13
- package/dist/client.js +275 -62
- package/dist/client.js.map +1 -1
- package/dist/index.cjs +205 -70
- 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 +2 -1
- package/dist/{plugin-BlfpqyX4.d.cts → plugin-DUTUA_t4.d.cts} +73 -19
- package/dist/{plugin-BlfpqyX4.d.ts → plugin-DUTUA_t4.d.ts} +73 -19
- package/dist/style.css +270 -25
- package/dist/vitepress.cjs +341 -138
- package/dist/vitepress.cjs.map +1 -1
- package/dist/vitepress.d.cts +17 -7
- package/dist/vitepress.d.ts +17 -7
- package/dist/vitepress.js +76 -8
- package/dist/vitepress.js.map +1 -1
- package/package.json +1 -1
- package/dist/chunk-PWNWSYI4.js.map +0 -1
package/dist/vitepress.cjs
CHANGED
|
@@ -30,6 +30,7 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
30
30
|
// src/vitepress.ts
|
|
31
31
|
var vitepress_exports = {};
|
|
32
32
|
__export(vitepress_exports, {
|
|
33
|
+
attachAnnouncements: () => attachAnnouncements,
|
|
33
34
|
blogHead: () => blogHead,
|
|
34
35
|
blogMarkdown: () => blogMarkdown,
|
|
35
36
|
blogPageData: () => blogPageData,
|
|
@@ -63,6 +64,11 @@ function hasAnyTag(post, tags) {
|
|
|
63
64
|
const wanted = new Set(tags.map((tag) => tag.toLowerCase()));
|
|
64
65
|
return post.post.tags.some((tag) => wanted.has(tag.toLowerCase()));
|
|
65
66
|
}
|
|
67
|
+
function inAnyCategory(post, categories) {
|
|
68
|
+
if (categories.length === 0) return true;
|
|
69
|
+
const category = post.post.category.toLowerCase();
|
|
70
|
+
return !!category && categories.some((wanted) => wanted.toLowerCase() === category);
|
|
71
|
+
}
|
|
66
72
|
function blogCoversPost(index, post, sections) {
|
|
67
73
|
if (index.index.scope === "section") return isInFolders(post.relativePath, index.index.folders);
|
|
68
74
|
if (!isInFolders(post.relativePath, index.index.folders)) return false;
|
|
@@ -76,22 +82,22 @@ function compareDates(a, b) {
|
|
|
76
82
|
function compareByDate(a, b) {
|
|
77
83
|
return compareDates(a.post.date, b.post.date) || a.post.title.localeCompare(b.post.title);
|
|
78
84
|
}
|
|
79
|
-
function
|
|
80
|
-
const
|
|
81
|
-
const pinned = new Set(limit ?
|
|
85
|
+
function pinPosts(posts, limit) {
|
|
86
|
+
const candidates = posts.filter((post) => post.post.pinned);
|
|
87
|
+
const pinned = new Set(limit ? candidates.slice(0, limit) : candidates);
|
|
82
88
|
return { pinned: [...pinned], rest: posts.filter((post) => !pinned.has(post)) };
|
|
83
89
|
}
|
|
84
90
|
function listBlogPosts(pages, index, options) {
|
|
85
91
|
const sections = pages.filter(isIndex).filter((page) => page.index.scope === "section");
|
|
86
|
-
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);
|
|
87
|
-
if (options.
|
|
88
|
-
const { pinned, rest } =
|
|
92
|
+
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);
|
|
93
|
+
if (options.pinnedFirst) {
|
|
94
|
+
const { pinned, rest } = pinPosts(posts, index.index.pinLimit);
|
|
89
95
|
posts = [...pinned, ...rest];
|
|
90
96
|
}
|
|
91
97
|
return options.applyLimit && index.index.limit ? posts.slice(0, index.index.limit) : posts;
|
|
92
98
|
}
|
|
93
99
|
function findHomeBlog(pages, post, drafts) {
|
|
94
|
-
const listing = pages.filter(isIndex).filter((index) => listBlogPosts(pages, index, { drafts,
|
|
100
|
+
const listing = pages.filter(isIndex).filter((index) => listBlogPosts(pages, index, { drafts, pinnedFirst: false, applyLimit: false }).includes(post));
|
|
95
101
|
const sections = listing.filter((index) => index.index.scope === "section");
|
|
96
102
|
if (sections.length) return deepestFirst(sections, post.relativePath)[0];
|
|
97
103
|
return listing[0] ?? null;
|
|
@@ -110,9 +116,120 @@ function findBlogForPage(pages, relativePath) {
|
|
|
110
116
|
}
|
|
111
117
|
function findBlogsListing(pages, post) {
|
|
112
118
|
return pages.filter(isIndex).filter(
|
|
113
|
-
(index) => listBlogPosts(pages, index, { drafts: false,
|
|
119
|
+
(index) => listBlogPosts(pages, index, { drafts: false, pinnedFirst: false, applyLimit: false }).includes(post)
|
|
114
120
|
);
|
|
115
121
|
}
|
|
122
|
+
function listAnnouncements(pages, drafts) {
|
|
123
|
+
return pages.filter(isPost).filter((post) => post.post.announcement && (drafts || !post.post.draft)).sort(compareByDate);
|
|
124
|
+
}
|
|
125
|
+
function findAnnouncementBlog(pages, announcements, drafts) {
|
|
126
|
+
if (announcements.length === 0) return null;
|
|
127
|
+
const listingAll = pages.filter(isIndex).filter((index) => {
|
|
128
|
+
const listed = listBlogPosts(pages, index, { drafts, pinnedFirst: false, applyLimit: false });
|
|
129
|
+
return announcements.every((post) => listed.includes(post));
|
|
130
|
+
});
|
|
131
|
+
return listingAll.find((index) => index.index.scope === "site") ?? listingAll[0] ?? findHomeBlog(pages, announcements[0], drafts);
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
// src/types.ts
|
|
135
|
+
var DEFAULT_LABELS = {
|
|
136
|
+
by: "By",
|
|
137
|
+
published: "Published",
|
|
138
|
+
updated: "Updated",
|
|
139
|
+
dateTime: "{date} at {time}",
|
|
140
|
+
readingTime: "{n} min read",
|
|
141
|
+
newer: "Newer post",
|
|
142
|
+
older: "Older post",
|
|
143
|
+
allPosts: "All posts in {blog}",
|
|
144
|
+
draft: "Draft",
|
|
145
|
+
pinned: "Pinned",
|
|
146
|
+
announcement: "Announcement",
|
|
147
|
+
announcements: "Announcements",
|
|
148
|
+
announcementCount: "{n} announcements",
|
|
149
|
+
dismiss: "Dismiss",
|
|
150
|
+
noPosts: "No posts yet.",
|
|
151
|
+
undated: "Undated",
|
|
152
|
+
browse: "Browse posts",
|
|
153
|
+
categories: "Categories",
|
|
154
|
+
tags: "Keywords",
|
|
155
|
+
archive: "Archive",
|
|
156
|
+
category: "Category",
|
|
157
|
+
tag: "Keyword",
|
|
158
|
+
postCount: "{n} posts",
|
|
159
|
+
postCountOne: "{n} post",
|
|
160
|
+
noMatches: "No posts match these filters.",
|
|
161
|
+
removeFilter: "Remove filter: {filter}",
|
|
162
|
+
showAll: "Show all posts",
|
|
163
|
+
previous: "Previous",
|
|
164
|
+
next: "Next",
|
|
165
|
+
pages: "Pages",
|
|
166
|
+
subscribe: "Subscribe",
|
|
167
|
+
rssFeed: "RSS feed for {blog}"
|
|
168
|
+
};
|
|
169
|
+
|
|
170
|
+
// src/util.ts
|
|
171
|
+
var HTML_ESCAPES = {
|
|
172
|
+
"&": "&",
|
|
173
|
+
"<": "<",
|
|
174
|
+
">": ">",
|
|
175
|
+
'"': """,
|
|
176
|
+
"'": "'"
|
|
177
|
+
};
|
|
178
|
+
function escapeHtml(value) {
|
|
179
|
+
return value.replace(/[&<>"']/g, (character) => HTML_ESCAPES[character]);
|
|
180
|
+
}
|
|
181
|
+
function escapeMarkdown(text) {
|
|
182
|
+
const escaped = text.replace(/[\\`*_[\]#|~]/g, "\\$&").replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">");
|
|
183
|
+
return /[{}]/.test(escaped) ? `<span v-pre>${escaped}</span>` : escaped;
|
|
184
|
+
}
|
|
185
|
+
function escapeTemplateText(text) {
|
|
186
|
+
const escaped = escapeHtml(text);
|
|
187
|
+
return /[{}]/.test(escaped) ? `<span v-pre>${escaped}</span>` : escaped;
|
|
188
|
+
}
|
|
189
|
+
function isExternalUrl(url) {
|
|
190
|
+
return /^(?:[a-z][a-z\d+.-]*:|\/\/)/i.test(url);
|
|
191
|
+
}
|
|
192
|
+
function toMarkdownUrl(url) {
|
|
193
|
+
return encodeURI(url).replace(/[()]/g, (character) => character === "(" ? "%28" : "%29");
|
|
194
|
+
}
|
|
195
|
+
function toPageLink(text, routePath) {
|
|
196
|
+
return `[${escapeMarkdown(text)}](${toMarkdownUrl(`/${routePath}`)})`;
|
|
197
|
+
}
|
|
198
|
+
function toUrlPath(routePath, cleanUrls) {
|
|
199
|
+
return `/${routePath.replace(/(^|\/)index\.md$/, "$1").replace(/\.md$/, cleanUrls ? "" : ".html")}`;
|
|
200
|
+
}
|
|
201
|
+
function joinUrl(base, urlPath) {
|
|
202
|
+
return `${base.replace(/\/+$/, "")}/${urlPath.replace(/^\/+/, "")}`;
|
|
203
|
+
}
|
|
204
|
+
var ANNOUNCEMENTS_KEY = "blogAnnouncements";
|
|
205
|
+
var DISMISSED_STORAGE_KEY = "vp-blog-announcements-dismissed";
|
|
206
|
+
var DISMISSED_CLASS = "vp-blog-announcement-dismissed";
|
|
207
|
+
|
|
208
|
+
// src/announcements.ts
|
|
209
|
+
function resolveAnnouncements(pages, options, cleanUrls) {
|
|
210
|
+
const drafts = options.drafts ?? false;
|
|
211
|
+
const announcements = listAnnouncements(pages, drafts);
|
|
212
|
+
if (announcements.length === 0) return null;
|
|
213
|
+
const blog = findAnnouncementBlog(pages, announcements, drafts);
|
|
214
|
+
const labels = { ...DEFAULT_LABELS, ...options.labels };
|
|
215
|
+
return {
|
|
216
|
+
items: announcements.map((post) => ({
|
|
217
|
+
id: `${post.routePath}@${post.post.date?.toISOString() ?? ""}`,
|
|
218
|
+
text: post.post.announcementText || post.post.title,
|
|
219
|
+
link: toUrlPath(post.routePath, cleanUrls)
|
|
220
|
+
})),
|
|
221
|
+
listLink: blog ? `${toUrlPath(blog.routePath, cleanUrls)}?announcements` : "",
|
|
222
|
+
labels: {
|
|
223
|
+
announcement: labels.announcement,
|
|
224
|
+
announcementCount: labels.announcementCount,
|
|
225
|
+
dismiss: labels.dismiss
|
|
226
|
+
}
|
|
227
|
+
};
|
|
228
|
+
}
|
|
229
|
+
function renderDismissedScript(data) {
|
|
230
|
+
const id = JSON.stringify(data.items[0].id).replace(/</g, "\\u003c");
|
|
231
|
+
return `try{var d=JSON.parse(localStorage.getItem(${JSON.stringify(DISMISSED_STORAGE_KEY)})||'[]');if(Array.isArray(d)&&d.indexOf(${id})>-1)document.documentElement.classList.add(${JSON.stringify(DISMISSED_CLASS)})}catch(e){}`;
|
|
232
|
+
}
|
|
116
233
|
|
|
117
234
|
// src/frontmatter.ts
|
|
118
235
|
var import_node_path = __toESM(require("path"), 1);
|
|
@@ -213,6 +330,13 @@ function toDateTimeAttribute({ date, hasTime }, timeZone) {
|
|
|
213
330
|
function yearIn(date, timeZone) {
|
|
214
331
|
return Number(toZonedIsoDate(date, timeZone).slice(0, 4));
|
|
215
332
|
}
|
|
333
|
+
function monthIn(date, timeZone) {
|
|
334
|
+
return toZonedIsoDate(date, timeZone).slice(0, 7);
|
|
335
|
+
}
|
|
336
|
+
function formatMonth(month, locale, format) {
|
|
337
|
+
const [year, number] = month.split("-").map(Number);
|
|
338
|
+
return new Intl.DateTimeFormat(locale, { timeZone: "UTC", ...format }).format(Date.UTC(year, number - 1, 1, 12));
|
|
339
|
+
}
|
|
216
340
|
|
|
217
341
|
// src/frontmatter.ts
|
|
218
342
|
var POST_FRONTMATTER_KEY = "blog";
|
|
@@ -320,6 +444,7 @@ function resolvePostData(data, content, fallbackTitle, options = {}) {
|
|
|
320
444
|
const timeZone = resolveTimeZone(options.timeZone);
|
|
321
445
|
const date = parsePostDate(pick("date"), timeZone);
|
|
322
446
|
const updated = parsePostDate(pick("updated"), timeZone);
|
|
447
|
+
const announcementText = typeof post.announcement === "string" ? clean(post.announcement.trim()) : "";
|
|
323
448
|
return {
|
|
324
449
|
title: clean(toText(post.title) || toText(data.title) || readHeading(content)) || fallbackTitle,
|
|
325
450
|
summary: clean(toText(post.summary) || toText(data.description) || readExcerpt(content)),
|
|
@@ -335,8 +460,11 @@ function resolvePostData(data, content, fallbackTitle, options = {}) {
|
|
|
335
460
|
tags: toStringList(pick("tags")),
|
|
336
461
|
category: toText(pick("category")),
|
|
337
462
|
scope: toScope(post.scope),
|
|
338
|
-
|
|
463
|
+
// `sticky` is this setting's old name.
|
|
464
|
+
pinned: (post.pinned ?? post.sticky) === true,
|
|
339
465
|
draft: post.draft === true,
|
|
466
|
+
announcement: post.announcement === true || !!announcementText,
|
|
467
|
+
announcementText,
|
|
340
468
|
byline: toBoolean(post.byline),
|
|
341
469
|
cover: toBoolean(post.cover),
|
|
342
470
|
postNav: toBoolean(post.postNav),
|
|
@@ -346,6 +474,9 @@ function resolvePostData(data, content, fallbackTitle, options = {}) {
|
|
|
346
474
|
function toLayout(value) {
|
|
347
475
|
return value === "grid" || value === "compact" ? value : "list";
|
|
348
476
|
}
|
|
477
|
+
function toGroupBy(value) {
|
|
478
|
+
return value === "year" || value === "month" ? value : "";
|
|
479
|
+
}
|
|
349
480
|
function defaultFeedPath(relativePath) {
|
|
350
481
|
const name = import_node_path.default.posix.basename(relativePath, ".md");
|
|
351
482
|
return name === "index" ? "feed.xml" : `${name}-feed.xml`;
|
|
@@ -379,13 +510,17 @@ function resolveIndexConfig(data, relativePath, defaults = {}) {
|
|
|
379
510
|
scope,
|
|
380
511
|
folders: folders.length ? resolveFolders(folders, relativePath) : scope === "section" ? [ownFolder] : [],
|
|
381
512
|
tags: toStringList(options.tags),
|
|
513
|
+
categories: toStringList(options.categories),
|
|
382
514
|
limit: typeof options.limit === "number" && options.limit > 0 ? Math.floor(options.limit) : 0,
|
|
383
515
|
layout: toLayout(options.layout),
|
|
384
|
-
|
|
516
|
+
groupBy: toGroupBy(options.groupBy),
|
|
385
517
|
showTags: options.showTags !== false,
|
|
518
|
+
showCategory: options.showCategory !== false,
|
|
519
|
+
categoryList: options.categoryList !== false,
|
|
386
520
|
tagList: options.tagList !== false,
|
|
521
|
+
archive: options.archive !== false,
|
|
387
522
|
pageSize: toCount(options.pageSize, toCount(defaults.pageSize, 10)),
|
|
388
|
-
|
|
523
|
+
pinLimit: toCount(options.pinLimit ?? options.stickyLimit, toCount(defaults.pinLimit ?? defaults.stickyLimit, 0)),
|
|
389
524
|
rssLink: typeof options.rssLink === "boolean" ? options.rssLink : defaults.rssLink ?? true,
|
|
390
525
|
feed: toFeed(options.feed, relativePath)
|
|
391
526
|
};
|
|
@@ -395,43 +530,6 @@ function resolveIndexConfig(data, relativePath, defaults = {}) {
|
|
|
395
530
|
var import_node_crypto = require("crypto");
|
|
396
531
|
var import_node_fs = require("fs");
|
|
397
532
|
var import_node_path2 = __toESM(require("path"), 1);
|
|
398
|
-
|
|
399
|
-
// src/util.ts
|
|
400
|
-
var HTML_ESCAPES = {
|
|
401
|
-
"&": "&",
|
|
402
|
-
"<": "<",
|
|
403
|
-
">": ">",
|
|
404
|
-
'"': """,
|
|
405
|
-
"'": "'"
|
|
406
|
-
};
|
|
407
|
-
function escapeHtml(value) {
|
|
408
|
-
return value.replace(/[&<>"']/g, (character) => HTML_ESCAPES[character]);
|
|
409
|
-
}
|
|
410
|
-
function escapeMarkdown(text) {
|
|
411
|
-
const escaped = text.replace(/[\\`*_[\]#|~]/g, "\\$&").replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">");
|
|
412
|
-
return /[{}]/.test(escaped) ? `<span v-pre>${escaped}</span>` : escaped;
|
|
413
|
-
}
|
|
414
|
-
function escapeTemplateText(text) {
|
|
415
|
-
const escaped = escapeHtml(text);
|
|
416
|
-
return /[{}]/.test(escaped) ? `<span v-pre>${escaped}</span>` : escaped;
|
|
417
|
-
}
|
|
418
|
-
function isExternalUrl(url) {
|
|
419
|
-
return /^(?:[a-z][a-z\d+.-]*:|\/\/)/i.test(url);
|
|
420
|
-
}
|
|
421
|
-
function toMarkdownUrl(url) {
|
|
422
|
-
return encodeURI(url).replace(/[()]/g, (character) => character === "(" ? "%28" : "%29");
|
|
423
|
-
}
|
|
424
|
-
function toPageLink(text, routePath) {
|
|
425
|
-
return `[${escapeMarkdown(text)}](${toMarkdownUrl(`/${routePath}`)})`;
|
|
426
|
-
}
|
|
427
|
-
function toUrlPath(routePath, cleanUrls) {
|
|
428
|
-
return `/${routePath.replace(/(^|\/)index\.md$/, "$1").replace(/\.md$/, cleanUrls ? "" : ".html")}`;
|
|
429
|
-
}
|
|
430
|
-
function joinUrl(base, urlPath) {
|
|
431
|
-
return `${base.replace(/\/+$/, "")}/${urlPath.replace(/^\/+/, "")}`;
|
|
432
|
-
}
|
|
433
|
-
|
|
434
|
-
// src/feed.ts
|
|
435
533
|
function toAbsoluteUrl(urlPath, site) {
|
|
436
534
|
return joinUrl(site.siteUrl, joinUrl(site.base, urlPath));
|
|
437
535
|
}
|
|
@@ -527,33 +625,6 @@ var import_node_path6 = __toESM(require("path"), 1);
|
|
|
527
625
|
|
|
528
626
|
// src/render.ts
|
|
529
627
|
var import_node_path3 = __toESM(require("path"), 1);
|
|
530
|
-
|
|
531
|
-
// src/types.ts
|
|
532
|
-
var DEFAULT_LABELS = {
|
|
533
|
-
by: "By",
|
|
534
|
-
published: "Published",
|
|
535
|
-
updated: "Updated",
|
|
536
|
-
dateTime: "{date} at {time}",
|
|
537
|
-
readingTime: "{n} min read",
|
|
538
|
-
newer: "Newer post",
|
|
539
|
-
older: "Older post",
|
|
540
|
-
allPosts: "All posts in {blog}",
|
|
541
|
-
draft: "Draft",
|
|
542
|
-
sticky: "Pinned",
|
|
543
|
-
noPosts: "No posts yet.",
|
|
544
|
-
undated: "Undated",
|
|
545
|
-
tags: "Keywords",
|
|
546
|
-
tagged: "Posts tagged {tag}",
|
|
547
|
-
showAll: "Show all posts",
|
|
548
|
-
noTagged: "No posts tagged {tag}.",
|
|
549
|
-
previous: "Previous",
|
|
550
|
-
next: "Next",
|
|
551
|
-
pages: "Pages",
|
|
552
|
-
subscribe: "Subscribe",
|
|
553
|
-
rssFeed: "RSS feed for {blog}"
|
|
554
|
-
};
|
|
555
|
-
|
|
556
|
-
// src/render.ts
|
|
557
628
|
var BLOG_POSTS_PLACEHOLDER = "<!-- blog-posts -->";
|
|
558
629
|
function createRenderContext(options, pageDirectory, feeds = !!options.siteUrl) {
|
|
559
630
|
const locale = options.locale ?? "en-US";
|
|
@@ -607,25 +678,41 @@ function renderAuthors(authors, context) {
|
|
|
607
678
|
function renderBadge(kind, context) {
|
|
608
679
|
return `<span class="vp-blog-badge vp-blog-badge--${kind}">${escapeTemplateText(context.labels[kind])}</span>`;
|
|
609
680
|
}
|
|
610
|
-
function
|
|
611
|
-
const
|
|
681
|
+
function toFilterUrl(blogRoutePath, param, value) {
|
|
682
|
+
const encoded = encodeURIComponent(value.toLowerCase()).replace(/[()]/g, (c) => c === "(" ? "%28" : "%29");
|
|
612
683
|
const page = blogRoutePath.replace(/(^|\/)index\.md$/, "$1");
|
|
613
|
-
return `${toMarkdownUrl(`/${page}`)}
|
|
684
|
+
return `${toMarkdownUrl(`/${page}`)}?${param}=${encoded}`;
|
|
685
|
+
}
|
|
686
|
+
function renderFilterLink(text, param, blogRoutePath, className) {
|
|
687
|
+
return blogRoutePath ? `[${escapeMarkdown(text)}](${toFilterUrl(blogRoutePath, param, text)})` : `<span class="${className}">${escapeTemplateText(text)}</span>`;
|
|
614
688
|
}
|
|
615
689
|
function renderTags(tags, blogRoutePath) {
|
|
616
|
-
return tags.map(
|
|
617
|
-
(tag) => blogRoutePath ? `[${escapeMarkdown(tag)}](${toTagUrl(blogRoutePath, tag)})` : `<span class="vp-blog-tag">${escapeTemplateText(tag)}</span>`
|
|
618
|
-
).join(" ");
|
|
690
|
+
return tags.map((tag) => renderFilterLink(tag, "tag", blogRoutePath, "vp-blog-tag")).join(" ");
|
|
619
691
|
}
|
|
620
692
|
function toTagsAttribute(post) {
|
|
621
693
|
return escapeHtml(post.post.tags.map((tag) => tag.toLowerCase()).join("|"));
|
|
622
694
|
}
|
|
695
|
+
function toItemAttributes(post, context) {
|
|
696
|
+
const { category, date, announcement } = post.post;
|
|
697
|
+
const attributes = [`data-vp-blog-item data-tags="${toTagsAttribute(post)}"`];
|
|
698
|
+
if (category) attributes.push(`data-category="${escapeHtml(category.toLowerCase())}"`);
|
|
699
|
+
if (date) attributes.push(`data-month="${monthIn(date, context.dates.timeZone)}"`);
|
|
700
|
+
if (announcement) attributes.push("data-announcement");
|
|
701
|
+
return attributes.join(" ");
|
|
702
|
+
}
|
|
703
|
+
function renderBadges(post, context) {
|
|
704
|
+
const { draft, pinned, announcement } = post.post;
|
|
705
|
+
return [
|
|
706
|
+
draft && renderBadge("draft", context),
|
|
707
|
+
pinned && renderBadge("pinned", context),
|
|
708
|
+
announcement && renderBadge("announcement", context)
|
|
709
|
+
].filter(Boolean).join(" ");
|
|
710
|
+
}
|
|
623
711
|
function renderMeta(post, context, include) {
|
|
624
|
-
const { date, dateHasTime, updated, updatedHasTime, readingMinutes, authors
|
|
712
|
+
const { date, dateHasTime, updated, updatedHasTime, readingMinutes, authors } = post.post;
|
|
625
713
|
const parts = [];
|
|
626
714
|
if (include.badges) {
|
|
627
|
-
const
|
|
628
|
-
const shown = badges.filter(Boolean).join(" ");
|
|
715
|
+
const shown = renderBadges(post, context);
|
|
629
716
|
if (shown) parts.push(shown);
|
|
630
717
|
}
|
|
631
718
|
if (date) {
|
|
@@ -652,16 +739,18 @@ function renderCard(post, context, index) {
|
|
|
652
739
|
const link = `/${post.routePath}`;
|
|
653
740
|
const image = toImageSource(post, context.pageDirectory);
|
|
654
741
|
const modifiers = [
|
|
655
|
-
post.post.
|
|
742
|
+
post.post.pinned && "pinned",
|
|
656
743
|
post.post.draft && "draft",
|
|
744
|
+
post.post.announcement && "announcement",
|
|
657
745
|
image && "with-image",
|
|
658
746
|
image && post.post.imageFit === "contain" && "contain"
|
|
659
747
|
].filter(Boolean).map((modifier) => ` vp-blog-card--${modifier}`).join("");
|
|
660
748
|
const alt = escapeMarkdown(post.post.imageAlt);
|
|
661
749
|
return [
|
|
662
|
-
`<article class="vp-blog-card${modifiers}"${imageStyle(post)}
|
|
750
|
+
`<article class="vp-blog-card${modifiers}"${imageStyle(post)} ${toItemAttributes(post, context)}>`,
|
|
663
751
|
...image ? block("vp-blog-card__image", `[})](${toMarkdownUrl(link)})`) : [],
|
|
664
752
|
'<div class="vp-blog-card__body">',
|
|
753
|
+
...index.index.showCategory && post.post.category ? block("vp-blog-card__category", renderFilterLink(post.post.category, "category", index.routePath, "")) : [],
|
|
665
754
|
...block("vp-blog-card__title", toPageLink(post.post.title, post.routePath)),
|
|
666
755
|
...block("vp-blog-card__meta", renderMeta(post, context, { authors: true, updated: false, badges: true })),
|
|
667
756
|
...block("vp-blog-card__summary", escapeMarkdown(post.post.summary)),
|
|
@@ -672,8 +761,8 @@ function renderCard(post, context, index) {
|
|
|
672
761
|
}
|
|
673
762
|
function renderCompactItem(post, context) {
|
|
674
763
|
const date = post.post.date ? `${renderTime(post.post.date, post.post.dateHasTime, context)} ` : "";
|
|
675
|
-
const badges =
|
|
676
|
-
const marker = `<span hidden
|
|
764
|
+
const badges = renderBadges(post, context);
|
|
765
|
+
const marker = `<span hidden ${toItemAttributes(post, context)}></span>`;
|
|
677
766
|
return `- ${marker}${date}${toPageLink(post.post.title, post.routePath)}${badges ? ` ${badges}` : ""}`;
|
|
678
767
|
}
|
|
679
768
|
function renderGroup(posts, index, context) {
|
|
@@ -693,18 +782,23 @@ function renderGroup(posts, index, context) {
|
|
|
693
782
|
"</div>"
|
|
694
783
|
];
|
|
695
784
|
}
|
|
696
|
-
function
|
|
697
|
-
const
|
|
785
|
+
function renderGroups(posts, index, context) {
|
|
786
|
+
const { groupBy } = index.index;
|
|
787
|
+
if (!groupBy) return renderGroup(posts, index, context);
|
|
788
|
+
const { timeZone, locale } = context.dates;
|
|
789
|
+
const groups = /* @__PURE__ */ new Map();
|
|
698
790
|
for (const post of posts) {
|
|
699
|
-
const
|
|
700
|
-
|
|
791
|
+
const { date } = post.post;
|
|
792
|
+
const key = !date ? "" : groupBy === "year" ? String(yearIn(date, timeZone)) : monthIn(date, timeZone);
|
|
793
|
+
groups.set(key, [...groups.get(key) ?? [], post]);
|
|
701
794
|
}
|
|
702
795
|
const lines = [];
|
|
703
|
-
for (const [
|
|
796
|
+
for (const [key, group] of groups) {
|
|
797
|
+
const heading = !key ? context.labels.undated : groupBy === "year" ? key : formatMonth(key, locale, { month: "long", year: "numeric" });
|
|
704
798
|
lines.push(
|
|
705
|
-
|
|
799
|
+
`<section class="vp-blog-group vp-blog-${groupBy}">`,
|
|
706
800
|
"",
|
|
707
|
-
`## ${escapeMarkdown(
|
|
801
|
+
`## ${escapeMarkdown(heading)}`,
|
|
708
802
|
"",
|
|
709
803
|
...renderGroup(group, index, context),
|
|
710
804
|
"",
|
|
@@ -713,42 +807,114 @@ function renderYears(posts, index, context) {
|
|
|
713
807
|
}
|
|
714
808
|
return lines;
|
|
715
809
|
}
|
|
716
|
-
function
|
|
717
|
-
const
|
|
810
|
+
function collectValues(posts, pick) {
|
|
811
|
+
const values = /* @__PURE__ */ new Map();
|
|
718
812
|
for (const post of posts) {
|
|
719
|
-
for (const
|
|
720
|
-
const entry =
|
|
813
|
+
for (const value of new Set(pick(post))) {
|
|
814
|
+
const entry = values.get(value.toLowerCase()) ?? { value, count: 0 };
|
|
721
815
|
entry.count++;
|
|
722
|
-
|
|
816
|
+
values.set(value.toLowerCase(), entry);
|
|
723
817
|
}
|
|
724
818
|
}
|
|
725
|
-
return [...
|
|
819
|
+
return [...values.values()].sort((a, b) => a.value.localeCompare(b.value, void 0, { sensitivity: "base" }));
|
|
726
820
|
}
|
|
727
|
-
function
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
821
|
+
function collectTags(posts) {
|
|
822
|
+
return collectValues(posts, (post) => post.post.tags).map(({ value, count }) => ({ tag: value, count }));
|
|
823
|
+
}
|
|
824
|
+
function collectCategories(posts) {
|
|
825
|
+
return collectValues(posts, (post) => post.post.category ? [post.post.category] : []);
|
|
826
|
+
}
|
|
827
|
+
function collectArchive(posts, timeZone) {
|
|
828
|
+
const years = /* @__PURE__ */ new Map();
|
|
829
|
+
for (const post of posts) {
|
|
830
|
+
if (!post.post.date) continue;
|
|
831
|
+
const month = monthIn(post.post.date, timeZone);
|
|
832
|
+
const year = years.get(month.slice(0, 4)) ?? { value: month.slice(0, 4), count: 0, months: [] };
|
|
833
|
+
year.count++;
|
|
834
|
+
const entry = year.months.find((candidate) => candidate.value === month);
|
|
835
|
+
if (entry) entry.count++;
|
|
836
|
+
else year.months.push({ value: month, count: 1 });
|
|
837
|
+
years.set(year.value, year);
|
|
838
|
+
}
|
|
839
|
+
const newestFirst = (a, b) => b.value.localeCompare(a.value);
|
|
840
|
+
return [...years.values()].sort(newestFirst).map((year) => ({ ...year, months: [...year.months].sort(newestFirst) }));
|
|
841
|
+
}
|
|
842
|
+
function renderChip(name, count, url, title = "") {
|
|
843
|
+
const tooltip = title ? ` "${title.replace(/"/g, """)}"` : "";
|
|
844
|
+
return `[<span class="vp-blog-facet__name">${escapeMarkdown(name)}</span> <span class="vp-blog-facet__count">${count}</span>](${url}${tooltip})`;
|
|
845
|
+
}
|
|
846
|
+
function renderFacet(facet, label, chips, ariaLabel = label, attributes = "") {
|
|
734
847
|
return [
|
|
735
|
-
`<
|
|
848
|
+
`<div class="vp-blog-facet vp-blog-facet--${facet}" role="group" aria-label="${escapeHtml(ariaLabel)}" data-vp-blog-facet="${facet}"${attributes}>`,
|
|
849
|
+
`<span class="vp-blog-facet__label" aria-hidden="true">${escapeTemplateText(label)}</span>`,
|
|
850
|
+
'<div class="vp-blog-facet__chips">',
|
|
736
851
|
"",
|
|
737
|
-
|
|
852
|
+
chips.join(" "),
|
|
738
853
|
"",
|
|
739
|
-
"</
|
|
854
|
+
"</div>",
|
|
855
|
+
"</div>"
|
|
740
856
|
];
|
|
741
857
|
}
|
|
858
|
+
function renderBrowse(posts, index, context) {
|
|
859
|
+
const { labels } = context;
|
|
860
|
+
const { locale, timeZone } = context.dates;
|
|
861
|
+
const blog = index.routePath;
|
|
862
|
+
const rows = [];
|
|
863
|
+
const categories = index.index.categoryList ? collectCategories(posts) : [];
|
|
864
|
+
if (categories.length) {
|
|
865
|
+
const chips = categories.map(({ value, count }) => renderChip(value, count, toFilterUrl(blog, "category", value)));
|
|
866
|
+
rows.push(...renderFacet("category", labels.categories, chips));
|
|
867
|
+
}
|
|
868
|
+
const tags = index.index.tagList ? collectTags(posts) : [];
|
|
869
|
+
if (tags.length) {
|
|
870
|
+
const chips = tags.map(({ tag, count }) => renderChip(tag, count, toFilterUrl(blog, "tag", tag)));
|
|
871
|
+
rows.push(...renderFacet("tag", labels.tags, chips));
|
|
872
|
+
}
|
|
873
|
+
const archive = index.index.archive ? collectArchive(posts, timeZone) : [];
|
|
874
|
+
if (archive.reduce((months, year) => months + year.months.length, 0) > 1) {
|
|
875
|
+
const years = archive.map(({ value, count }) => renderChip(value, count, toFilterUrl(blog, "year", value)));
|
|
876
|
+
rows.push(...renderFacet("year", labels.archive, years));
|
|
877
|
+
for (const year of archive) {
|
|
878
|
+
const months = year.months.map(
|
|
879
|
+
({ value, count }) => renderChip(
|
|
880
|
+
formatMonth(value, locale, { month: "short" }),
|
|
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
|
+
);
|
|
896
|
+
}
|
|
897
|
+
}
|
|
898
|
+
if (rows.length === 0) return [];
|
|
899
|
+
return [`<nav class="vp-blog-browse" aria-label="${escapeHtml(labels.browse)}">`, ...rows, "</nav>"];
|
|
900
|
+
}
|
|
742
901
|
function renderClientAttributes(index, context) {
|
|
743
902
|
const { labels } = context;
|
|
744
903
|
const attributes = {
|
|
745
904
|
"data-page-size": String(index.index.pageSize),
|
|
746
|
-
"
|
|
905
|
+
// For writing a `?month=` filter's name: "October 2026".
|
|
906
|
+
"data-locale": context.locale,
|
|
747
907
|
"data-label-show-all": labels.showAll,
|
|
748
|
-
"data-label-no-tagged": labels.noTagged,
|
|
749
908
|
"data-label-previous": labels.previous,
|
|
750
909
|
"data-label-next": labels.next,
|
|
751
|
-
"data-label-pages": labels.pages
|
|
910
|
+
"data-label-pages": labels.pages,
|
|
911
|
+
"data-label-announcements": labels.announcements,
|
|
912
|
+
"data-label-category": labels.category,
|
|
913
|
+
"data-label-tag": labels.tag,
|
|
914
|
+
"data-label-post-count": labels.postCount,
|
|
915
|
+
"data-label-post-count-one": labels.postCountOne,
|
|
916
|
+
"data-label-no-matches": labels.noMatches,
|
|
917
|
+
"data-label-remove-filter": labels.removeFilter
|
|
752
918
|
};
|
|
753
919
|
return Object.entries(attributes).map(([name, value]) => `${name}="${escapeHtml(value)}"`).join(" ");
|
|
754
920
|
}
|
|
@@ -759,17 +925,16 @@ function renderPostList(pinned, rest, index, context) {
|
|
|
759
925
|
const lines = [
|
|
760
926
|
`<div class="vp-blog" data-vp-blog ${renderClientAttributes(index, context)}>`,
|
|
761
927
|
...block("vp-blog-subscribe", renderRssLink(index, context)),
|
|
762
|
-
...
|
|
763
|
-
'<div class="vp-blog-filter" data-vp-blog-filter hidden></div>'
|
|
928
|
+
...renderBrowse(all, index, context),
|
|
929
|
+
'<div class="vp-blog-filter" data-vp-blog-filter role="status" hidden></div>'
|
|
764
930
|
];
|
|
765
931
|
if (pinned.length)
|
|
766
932
|
lines.push(
|
|
767
|
-
'<section class="vp-blog-
|
|
933
|
+
'<section class="vp-blog-pinned" data-vp-blog-pinned>',
|
|
768
934
|
...renderGroup(pinned, index, context),
|
|
769
935
|
"</section>"
|
|
770
936
|
);
|
|
771
|
-
if (rest.length)
|
|
772
|
-
lines.push(...index.index.groupByYear ? renderYears(rest, index, context) : renderGroup(rest, index, context));
|
|
937
|
+
if (rest.length) lines.push(...renderGroups(rest, index, context));
|
|
773
938
|
lines.push(`<nav class="vp-blog-pagination" data-vp-blog-pagination hidden></nav>`, "</div>");
|
|
774
939
|
return `${lines.join("\n")}
|
|
775
940
|
`;
|
|
@@ -778,8 +943,12 @@ function renderPostHeader(post, context, show, blogRoutePath = null) {
|
|
|
778
943
|
const lines = [];
|
|
779
944
|
if (show.byline) {
|
|
780
945
|
const meta = renderMeta(post, context, { authors: true, updated: true, badges: true });
|
|
781
|
-
const
|
|
782
|
-
|
|
946
|
+
const { category, tags } = post.post;
|
|
947
|
+
const chips = [
|
|
948
|
+
category && `<span class="vp-blog-byline__category">${renderFilterLink(category, "category", blogRoutePath, "vp-blog-category")}</span>`,
|
|
949
|
+
tags.length && `<span class="vp-blog-byline__tags">${renderTags(tags, blogRoutePath)}</span>`
|
|
950
|
+
].filter(Boolean).join(" ");
|
|
951
|
+
lines.push(...block("vp-blog-byline", [meta, chips].filter(Boolean).join("\n\n")));
|
|
783
952
|
}
|
|
784
953
|
if (show.cover && post.post.image) {
|
|
785
954
|
const image = /^[./@~]/.test(post.post.image) || isExternalUrl(post.post.image) ? post.post.image : `./${post.post.image}`;
|
|
@@ -870,7 +1039,7 @@ function toOptionsKey(options) {
|
|
|
870
1039
|
options.wordsPerMinute,
|
|
871
1040
|
options.stripTags,
|
|
872
1041
|
options.pageSize,
|
|
873
|
-
options.stickyLimit,
|
|
1042
|
+
options.pinLimit ?? options.stickyLimit,
|
|
874
1043
|
options.rssLink,
|
|
875
1044
|
options.timeZone
|
|
876
1045
|
]);
|
|
@@ -959,10 +1128,13 @@ function resolveWidgetConfig(body) {
|
|
|
959
1128
|
config: {
|
|
960
1129
|
blog: typeof data.blog === "string" ? data.blog.trim() : "",
|
|
961
1130
|
limit: toCount2(data.limit) ?? DEFAULT_LIMIT,
|
|
962
|
-
stickyLimit
|
|
1131
|
+
// `stickyLimit` is this setting's old name.
|
|
1132
|
+
pinLimit: toCount2(data.pinLimit ?? data.stickyLimit),
|
|
963
1133
|
layout,
|
|
964
1134
|
showTags: typeof data.showTags === "boolean" ? data.showTags : void 0,
|
|
1135
|
+
showCategory: typeof data.showCategory === "boolean" ? data.showCategory : void 0,
|
|
965
1136
|
tags: toStringList(data.tags),
|
|
1137
|
+
categories: toStringList(data.categories),
|
|
966
1138
|
more: data.more === false ? null : typeof data.more === "string" && data.more.trim() ? data.more.trim() : "",
|
|
967
1139
|
rssLink: typeof data.rssLink === "boolean" ? data.rssLink : void 0
|
|
968
1140
|
},
|
|
@@ -978,19 +1150,19 @@ function renderWidget(body, environment) {
|
|
|
978
1150
|
warn(config.blog ? `no blog page found at "${config.blog}"` : 'no blog covers this page: name one with "blog:"');
|
|
979
1151
|
return "";
|
|
980
1152
|
}
|
|
981
|
-
const
|
|
982
|
-
const
|
|
983
|
-
|
|
984
|
-
(post) => wanted.size === 0 || post.post.tags.some((tag) => wanted.has(tag.toLowerCase()))
|
|
1153
|
+
const pinLimit = config.pinLimit ?? blog.index.pinLimit;
|
|
1154
|
+
const posts = listBlogPosts(pages, blog, { drafts, pinnedFirst: false, applyLimit: false }).filter(
|
|
1155
|
+
(post) => hasAnyTag(post, config.tags) && inAnyCategory(post, config.categories)
|
|
985
1156
|
);
|
|
986
|
-
const { pinned, rest } =
|
|
1157
|
+
const { pinned, rest } = pinPosts(posts, pinLimit);
|
|
987
1158
|
const shown = [...pinned, ...rest].slice(0, config.limit || void 0);
|
|
988
1159
|
const view = {
|
|
989
1160
|
...blog,
|
|
990
1161
|
index: {
|
|
991
1162
|
...blog.index,
|
|
992
1163
|
layout: config.layout ?? blog.index.layout,
|
|
993
|
-
showTags: config.showTags ?? blog.index.showTags
|
|
1164
|
+
showTags: config.showTags ?? blog.index.showTags,
|
|
1165
|
+
showCategory: config.showCategory ?? blog.index.showCategory
|
|
994
1166
|
}
|
|
995
1167
|
};
|
|
996
1168
|
const lines = [`<div class="vp-blog-widget">`];
|
|
@@ -1063,8 +1235,8 @@ function hasFeeds(options) {
|
|
|
1063
1235
|
}
|
|
1064
1236
|
function withPostList(source, page, pages, options) {
|
|
1065
1237
|
if (!isIndex(page)) return source;
|
|
1066
|
-
const posts = listBlogPosts(pages, page, { drafts: options.drafts ?? false,
|
|
1067
|
-
const { pinned, rest } =
|
|
1238
|
+
const posts = listBlogPosts(pages, page, { drafts: options.drafts ?? false, pinnedFirst: true, applyLimit: true });
|
|
1239
|
+
const { pinned, rest } = pinPosts(posts, page.index.pinLimit);
|
|
1068
1240
|
const context = createRenderContext(options, import_node_path6.default.dirname(page.absolutePath), hasFeeds(options));
|
|
1069
1241
|
const generated = renderPostList(pinned, rest, page, context);
|
|
1070
1242
|
return source.includes(BLOG_POSTS_PLACEHOLDER) ? source.replace(BLOG_POSTS_PLACEHOLDER, () => `
|
|
@@ -1087,7 +1259,7 @@ function withPostDecorations(source, page, pages, options) {
|
|
|
1087
1259
|
let result = header ? insertAfterTitle(source, header) : source;
|
|
1088
1260
|
if (page.post.postNav ?? options.postNav ?? true) {
|
|
1089
1261
|
if (blog) {
|
|
1090
|
-
const posts = listBlogPosts(pages, blog, { drafts,
|
|
1262
|
+
const posts = listBlogPosts(pages, blog, { drafts, pinnedFirst: false, applyLimit: false });
|
|
1091
1263
|
result = `${result.replace(/\s*$/, "")}
|
|
1092
1264
|
|
|
1093
1265
|
${renderPostNav(page, posts, blog, context)}
|
|
@@ -1135,6 +1307,9 @@ function blogMarkdown(md, options = {}) {
|
|
|
1135
1307
|
|
|
1136
1308
|
// src/vitepress.ts
|
|
1137
1309
|
var DEFAULT_FEED_LIMIT = 20;
|
|
1310
|
+
var PACKAGE_NAME = "@binarynoir/vitepress-blog";
|
|
1311
|
+
var SITE_DATA_MODULE = "/@siteData";
|
|
1312
|
+
var SCRIPT_MARKER = "data-vp-blog-announcement";
|
|
1138
1313
|
function resolveSiteLocation(siteConfig, options) {
|
|
1139
1314
|
const siteUrl = options.siteUrl ?? siteConfig.userConfig?.sitemap?.hostname ?? siteConfig.sitemap?.hostname;
|
|
1140
1315
|
if (!siteUrl) return null;
|
|
@@ -1149,9 +1324,19 @@ function resolveSiteLocation(siteConfig, options) {
|
|
|
1149
1324
|
function loadPages(siteConfig, options) {
|
|
1150
1325
|
return loadBlogPages(siteConfig.srcDir, options, siteConfig);
|
|
1151
1326
|
}
|
|
1327
|
+
function attachAnnouncements(siteConfig, options = {}) {
|
|
1328
|
+
const site = siteConfig.site;
|
|
1329
|
+
const data = resolveAnnouncements(loadPages(siteConfig, options), options, !!siteConfig.cleanUrls);
|
|
1330
|
+
const changed = JSON.stringify(site[ANNOUNCEMENTS_KEY] ?? null) !== JSON.stringify(data);
|
|
1331
|
+
if (data) site[ANNOUNCEMENTS_KEY] = data;
|
|
1332
|
+
else delete site[ANNOUNCEMENTS_KEY];
|
|
1333
|
+
site.head = (site.head ?? []).filter(([, attributes]) => !(SCRIPT_MARKER in (attributes ?? {})));
|
|
1334
|
+
if (data) site.head.push(["script", { [SCRIPT_MARKER]: "" }, renderDismissedScript(data)]);
|
|
1335
|
+
return changed;
|
|
1336
|
+
}
|
|
1152
1337
|
function listFeedPosts(pages, index, options) {
|
|
1153
1338
|
const limit = index.index.feed?.limit ?? options.feedLimit ?? DEFAULT_FEED_LIMIT;
|
|
1154
|
-
return listBlogPosts(pages, index, { drafts: false,
|
|
1339
|
+
return listBlogPosts(pages, index, { drafts: false, pinnedFirst: false, applyLimit: false }).slice(0, limit);
|
|
1155
1340
|
}
|
|
1156
1341
|
function renderIndexFeed(pages, index, site, siteConfig, options) {
|
|
1157
1342
|
return renderFeed({
|
|
@@ -1253,11 +1438,26 @@ function blogVitePlugin(options = {}) {
|
|
|
1253
1438
|
let siteConfig;
|
|
1254
1439
|
const currentPages = () => siteConfig ? loadPages(siteConfig, options) : [];
|
|
1255
1440
|
const dependentFiles = () => [...currentPages().map((page) => page.absolutePath), ...widgetPages];
|
|
1441
|
+
const invalidate = (server, files) => {
|
|
1442
|
+
for (const file of files) {
|
|
1443
|
+
for (const module2 of server.moduleGraph.getModulesByFile(file) ?? []) server.moduleGraph.invalidateModule(module2);
|
|
1444
|
+
}
|
|
1445
|
+
};
|
|
1446
|
+
const refreshAnnouncements = (server) => {
|
|
1447
|
+
if (!siteConfig || !attachAnnouncements(siteConfig, options)) return false;
|
|
1448
|
+
const module2 = server.moduleGraph.getModuleById(SITE_DATA_MODULE);
|
|
1449
|
+
if (module2) server.moduleGraph.invalidateModule(module2);
|
|
1450
|
+
return true;
|
|
1451
|
+
};
|
|
1256
1452
|
return {
|
|
1257
1453
|
name: "vitepress-blog",
|
|
1258
1454
|
enforce: "pre",
|
|
1455
|
+
config() {
|
|
1456
|
+
return { ssr: { noExternal: [PACKAGE_NAME] } };
|
|
1457
|
+
},
|
|
1259
1458
|
configResolved(config) {
|
|
1260
1459
|
siteConfig = config.vitepress;
|
|
1460
|
+
if (siteConfig) attachAnnouncements(siteConfig, options);
|
|
1261
1461
|
},
|
|
1262
1462
|
transform(code, id) {
|
|
1263
1463
|
if (!siteConfig || !id.endsWith(".md") || !(mayHaveBlogFrontmatter(code) || hasWidget(code))) return null;
|
|
@@ -1268,11 +1468,8 @@ function blogVitePlugin(options = {}) {
|
|
|
1268
1468
|
configureServer(server) {
|
|
1269
1469
|
const refresh = (file) => {
|
|
1270
1470
|
if (!siteConfig || !file.endsWith(".md")) return;
|
|
1271
|
-
|
|
1272
|
-
|
|
1273
|
-
server.moduleGraph.invalidateModule(module2);
|
|
1274
|
-
}
|
|
1275
|
-
}
|
|
1471
|
+
invalidate(server, dependentFiles());
|
|
1472
|
+
refreshAnnouncements(server);
|
|
1276
1473
|
server.ws.send({ type: "full-reload" });
|
|
1277
1474
|
};
|
|
1278
1475
|
server.watcher.on("add", refresh).on("unlink", refresh);
|
|
@@ -1303,6 +1500,11 @@ function blogVitePlugin(options = {}) {
|
|
|
1303
1500
|
},
|
|
1304
1501
|
handleHotUpdate({ file, modules, server }) {
|
|
1305
1502
|
if (!siteConfig || !file.endsWith(".md")) return;
|
|
1503
|
+
if (refreshAnnouncements(server)) {
|
|
1504
|
+
invalidate(server, dependentFiles());
|
|
1505
|
+
server.ws.send({ type: "full-reload" });
|
|
1506
|
+
return [];
|
|
1507
|
+
}
|
|
1306
1508
|
const pages = currentPages();
|
|
1307
1509
|
if (!pages.some((page) => page.absolutePath === file)) return;
|
|
1308
1510
|
const affected = dependentFiles().filter((dependent) => dependent !== file).flatMap((dependent) => [...server.moduleGraph.getModulesByFile(dependent) ?? []]);
|
|
@@ -1339,6 +1541,7 @@ function withBlog(config, options = {}) {
|
|
|
1339
1541
|
}
|
|
1340
1542
|
// Annotate the CommonJS export names for ESM import in node:
|
|
1341
1543
|
0 && (module.exports = {
|
|
1544
|
+
attachAnnouncements,
|
|
1342
1545
|
blogHead,
|
|
1343
1546
|
blogMarkdown,
|
|
1344
1547
|
blogPageData,
|