@docusaurus/plugin-content-blog 3.3.2 → 3.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/lib/blogUtils.d.ts +1 -9
- package/lib/blogUtils.js +17 -22
- package/lib/feed.d.ts +5 -1
- package/lib/feed.js +44 -1
- package/lib/index.js +109 -101
- package/lib/markdownLoader.js +2 -6
- package/lib/options.js +9 -0
- package/lib/props.js +2 -0
- package/lib/types.d.ts +1 -8
- package/package.json +9 -9
- package/src/blogUtils.ts +21 -43
- package/src/feed.ts +57 -1
- package/src/index.ts +151 -136
- package/src/markdownLoader.ts +3 -7
- package/src/options.ts +9 -0
- package/src/plugin-content-blog.d.ts +102 -101
- package/src/props.ts +2 -0
- package/src/types.ts +1 -6
package/lib/blogUtils.d.ts
CHANGED
|
@@ -7,11 +7,8 @@
|
|
|
7
7
|
/// <reference path="../src/plugin-content-blog.d.ts" />
|
|
8
8
|
import type { LoadContext } from '@docusaurus/types';
|
|
9
9
|
import type { PluginOptions, BlogPost, BlogTags, BlogPaginated } from '@docusaurus/plugin-content-blog';
|
|
10
|
-
import type { BlogContentPaths
|
|
10
|
+
import type { BlogContentPaths } from './types';
|
|
11
11
|
export declare function truncate(fileString: string, truncateMarker: RegExp): string;
|
|
12
|
-
export declare function getSourceToPermalink(blogPosts: BlogPost[]): {
|
|
13
|
-
[aliasedPath: string]: string;
|
|
14
|
-
};
|
|
15
12
|
export declare function paginateBlogPosts({ blogPosts, basePageUrl, blogTitle, blogDescription, postsPerPageOption, pageBasePath, }: {
|
|
16
13
|
blogPosts: BlogPost[];
|
|
17
14
|
basePageUrl: string;
|
|
@@ -35,11 +32,6 @@ type ParsedBlogFileName = {
|
|
|
35
32
|
};
|
|
36
33
|
export declare function parseBlogFileName(blogSourceRelative: string): ParsedBlogFileName;
|
|
37
34
|
export declare function generateBlogPosts(contentPaths: BlogContentPaths, context: LoadContext, options: PluginOptions): Promise<BlogPost[]>;
|
|
38
|
-
export type LinkifyParams = {
|
|
39
|
-
filePath: string;
|
|
40
|
-
fileString: string;
|
|
41
|
-
} & Pick<BlogMarkdownLoaderOptions, 'sourceToPermalink' | 'siteDir' | 'contentPaths' | 'onBrokenMarkdownLink'>;
|
|
42
|
-
export declare function linkify({ filePath, contentPaths, fileString, siteDir, sourceToPermalink, onBrokenMarkdownLink, }: LinkifyParams): string;
|
|
43
35
|
export declare function applyProcessBlogPosts({ blogPosts, processBlogPosts, }: {
|
|
44
36
|
blogPosts: BlogPost[];
|
|
45
37
|
processBlogPosts: PluginOptions['processBlogPosts'];
|
package/lib/blogUtils.js
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
* LICENSE file in the root directory of this source tree.
|
|
7
7
|
*/
|
|
8
8
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
|
-
exports.applyProcessBlogPosts = exports.
|
|
9
|
+
exports.applyProcessBlogPosts = exports.generateBlogPosts = exports.parseBlogFileName = exports.getBlogTags = exports.shouldBeListed = exports.paginateBlogPosts = exports.truncate = void 0;
|
|
10
10
|
const tslib_1 = require("tslib");
|
|
11
11
|
const fs_extra_1 = tslib_1.__importDefault(require("fs-extra"));
|
|
12
12
|
const path_1 = tslib_1.__importDefault(require("path"));
|
|
@@ -14,16 +14,13 @@ const lodash_1 = tslib_1.__importDefault(require("lodash"));
|
|
|
14
14
|
const logger_1 = tslib_1.__importDefault(require("@docusaurus/logger"));
|
|
15
15
|
const reading_time_1 = tslib_1.__importDefault(require("reading-time"));
|
|
16
16
|
const utils_1 = require("@docusaurus/utils");
|
|
17
|
+
const utils_validation_1 = require("@docusaurus/utils-validation");
|
|
17
18
|
const frontMatter_1 = require("./frontMatter");
|
|
18
19
|
const authors_1 = require("./authors");
|
|
19
20
|
function truncate(fileString, truncateMarker) {
|
|
20
21
|
return fileString.split(truncateMarker, 1).shift();
|
|
21
22
|
}
|
|
22
23
|
exports.truncate = truncate;
|
|
23
|
-
function getSourceToPermalink(blogPosts) {
|
|
24
|
-
return Object.fromEntries(blogPosts.map(({ metadata: { source, permalink } }) => [source, permalink]));
|
|
25
|
-
}
|
|
26
|
-
exports.getSourceToPermalink = getSourceToPermalink;
|
|
27
24
|
function paginateBlogPosts({ blogPosts, basePageUrl, blogTitle, blogDescription, postsPerPageOption, pageBasePath, }) {
|
|
28
25
|
const totalCount = blogPosts.length;
|
|
29
26
|
const postsPerPage = postsPerPageOption === 'ALL' ? totalCount : postsPerPageOption;
|
|
@@ -67,9 +64,11 @@ function getBlogTags({ blogPosts, ...params }) {
|
|
|
67
64
|
isUnlisted: (item) => item.metadata.unlisted,
|
|
68
65
|
});
|
|
69
66
|
return {
|
|
67
|
+
inline: tag.inline,
|
|
70
68
|
label: tag.label,
|
|
71
|
-
items: tagVisibility.listedItems.map((item) => item.id),
|
|
72
69
|
permalink: tag.permalink,
|
|
70
|
+
description: tag.description,
|
|
71
|
+
items: tagVisibility.listedItems.map((item) => item.id),
|
|
73
72
|
pages: paginateBlogPosts({
|
|
74
73
|
blogPosts: tagVisibility.listedItems,
|
|
75
74
|
basePageUrl: tag.permalink,
|
|
@@ -116,7 +115,7 @@ async function parseBlogPostMarkdownFile({ filePath, parseFrontMatter, }) {
|
|
|
116
115
|
}
|
|
117
116
|
}
|
|
118
117
|
const defaultReadingTime = ({ content, options }) => (0, reading_time_1.default)(content, options).minutes;
|
|
119
|
-
async function processBlogSourceFile(blogSourceRelative, contentPaths, context, options, authorsMap) {
|
|
118
|
+
async function processBlogSourceFile(blogSourceRelative, contentPaths, context, options, tagsFile, authorsMap) {
|
|
120
119
|
const { siteConfig: { baseUrl, markdown: { parseFrontMatter }, }, siteDir, i18n, } = context;
|
|
121
120
|
const { routeBasePath, tagsBasePath: tagsRouteBasePath, truncateMarker, showReadingTime, editUrl, } = options;
|
|
122
121
|
// Lookup in localized folder in priority
|
|
@@ -190,12 +189,19 @@ async function processBlogSourceFile(blogSourceRelative, contentPaths, context,
|
|
|
190
189
|
}
|
|
191
190
|
return undefined;
|
|
192
191
|
}
|
|
193
|
-
const
|
|
192
|
+
const tagsBaseRoutePath = (0, utils_1.normalizeUrl)([
|
|
194
193
|
baseUrl,
|
|
195
194
|
routeBasePath,
|
|
196
195
|
tagsRouteBasePath,
|
|
197
196
|
]);
|
|
198
197
|
const authors = (0, authors_1.getBlogPostAuthors)({ authorsMap, frontMatter, baseUrl });
|
|
198
|
+
const tags = (0, utils_1.normalizeTags)({
|
|
199
|
+
options,
|
|
200
|
+
source: blogSourceRelative,
|
|
201
|
+
frontMatterTags: frontMatter.tags,
|
|
202
|
+
tagsBaseRoutePath,
|
|
203
|
+
tagsFile,
|
|
204
|
+
});
|
|
199
205
|
return {
|
|
200
206
|
id: slug,
|
|
201
207
|
metadata: {
|
|
@@ -205,7 +211,7 @@ async function processBlogSourceFile(blogSourceRelative, contentPaths, context,
|
|
|
205
211
|
title,
|
|
206
212
|
description,
|
|
207
213
|
date,
|
|
208
|
-
tags
|
|
214
|
+
tags,
|
|
209
215
|
readingTime: showReadingTime
|
|
210
216
|
? options.readingTime({
|
|
211
217
|
content,
|
|
@@ -236,9 +242,10 @@ async function generateBlogPosts(contentPaths, context, options) {
|
|
|
236
242
|
contentPaths,
|
|
237
243
|
authorsMapPath: options.authorsMapPath,
|
|
238
244
|
});
|
|
245
|
+
const tagsFile = await (0, utils_validation_1.getTagsFile)({ contentPaths, tags: options.tags });
|
|
239
246
|
async function doProcessBlogSourceFile(blogSourceFile) {
|
|
240
247
|
try {
|
|
241
|
-
return await processBlogSourceFile(blogSourceFile, contentPaths, context, options, authorsMap);
|
|
248
|
+
return await processBlogSourceFile(blogSourceFile, contentPaths, context, options, tagsFile, authorsMap);
|
|
242
249
|
}
|
|
243
250
|
catch (err) {
|
|
244
251
|
throw new Error(`Processing of blog source file path=${blogSourceFile} failed.`, { cause: err });
|
|
@@ -252,18 +259,6 @@ async function generateBlogPosts(contentPaths, context, options) {
|
|
|
252
259
|
return blogPosts;
|
|
253
260
|
}
|
|
254
261
|
exports.generateBlogPosts = generateBlogPosts;
|
|
255
|
-
function linkify({ filePath, contentPaths, fileString, siteDir, sourceToPermalink, onBrokenMarkdownLink, }) {
|
|
256
|
-
const { newContent, brokenMarkdownLinks } = (0, utils_1.replaceMarkdownLinks)({
|
|
257
|
-
siteDir,
|
|
258
|
-
fileString,
|
|
259
|
-
filePath,
|
|
260
|
-
contentPaths,
|
|
261
|
-
sourceToPermalink,
|
|
262
|
-
});
|
|
263
|
-
brokenMarkdownLinks.forEach((l) => onBrokenMarkdownLink(l));
|
|
264
|
-
return newContent;
|
|
265
|
-
}
|
|
266
|
-
exports.linkify = linkify;
|
|
267
262
|
async function applyProcessBlogPosts({ blogPosts, processBlogPosts, }) {
|
|
268
263
|
const processedBlogPosts = await processBlogPosts({ blogPosts });
|
|
269
264
|
if (Array.isArray(processedBlogPosts)) {
|
package/lib/feed.d.ts
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
* LICENSE file in the root directory of this source tree.
|
|
6
6
|
*/
|
|
7
7
|
/// <reference path="../src/plugin-content-blog.d.ts" />
|
|
8
|
-
import type { DocusaurusConfig } from '@docusaurus/types';
|
|
8
|
+
import type { DocusaurusConfig, HtmlTags, LoadContext } from '@docusaurus/types';
|
|
9
9
|
import type { PluginOptions, BlogPost } from '@docusaurus/plugin-content-blog';
|
|
10
10
|
export declare function createBlogFeedFiles({ blogPosts: allBlogPosts, options, siteConfig, outDir, locale, }: {
|
|
11
11
|
blogPosts: BlogPost[];
|
|
@@ -14,3 +14,7 @@ export declare function createBlogFeedFiles({ blogPosts: allBlogPosts, options,
|
|
|
14
14
|
outDir: string;
|
|
15
15
|
locale: string;
|
|
16
16
|
}): Promise<void>;
|
|
17
|
+
export declare function createFeedHtmlHeadTags({ context, options, }: {
|
|
18
|
+
context: LoadContext;
|
|
19
|
+
options: PluginOptions;
|
|
20
|
+
}): HtmlTags;
|
package/lib/feed.js
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
* LICENSE file in the root directory of this source tree.
|
|
7
7
|
*/
|
|
8
8
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
|
-
exports.createBlogFeedFiles = void 0;
|
|
9
|
+
exports.createFeedHtmlHeadTags = exports.createBlogFeedFiles = void 0;
|
|
10
10
|
const tslib_1 = require("tslib");
|
|
11
11
|
const path_1 = tslib_1.__importDefault(require("path"));
|
|
12
12
|
const fs_extra_1 = tslib_1.__importDefault(require("fs-extra"));
|
|
@@ -151,3 +151,46 @@ async function createBlogFeedFiles({ blogPosts: allBlogPosts, options, siteConfi
|
|
|
151
151
|
})));
|
|
152
152
|
}
|
|
153
153
|
exports.createBlogFeedFiles = createBlogFeedFiles;
|
|
154
|
+
function createFeedHtmlHeadTags({ context, options, }) {
|
|
155
|
+
const feedTypes = options.feedOptions.type;
|
|
156
|
+
if (!feedTypes) {
|
|
157
|
+
return [];
|
|
158
|
+
}
|
|
159
|
+
const feedTitle = options.feedOptions.title ?? context.siteConfig.title;
|
|
160
|
+
const feedsConfig = {
|
|
161
|
+
rss: {
|
|
162
|
+
type: 'application/rss+xml',
|
|
163
|
+
path: 'rss.xml',
|
|
164
|
+
title: `${feedTitle} RSS Feed`,
|
|
165
|
+
},
|
|
166
|
+
atom: {
|
|
167
|
+
type: 'application/atom+xml',
|
|
168
|
+
path: 'atom.xml',
|
|
169
|
+
title: `${feedTitle} Atom Feed`,
|
|
170
|
+
},
|
|
171
|
+
json: {
|
|
172
|
+
type: 'application/json',
|
|
173
|
+
path: 'feed.json',
|
|
174
|
+
title: `${feedTitle} JSON Feed`,
|
|
175
|
+
},
|
|
176
|
+
};
|
|
177
|
+
const headTags = [];
|
|
178
|
+
feedTypes.forEach((feedType) => {
|
|
179
|
+
const { type, path: feedConfigPath, title: feedConfigTitle, } = feedsConfig[feedType];
|
|
180
|
+
headTags.push({
|
|
181
|
+
tagName: 'link',
|
|
182
|
+
attributes: {
|
|
183
|
+
rel: 'alternate',
|
|
184
|
+
type,
|
|
185
|
+
href: (0, utils_1.normalizeUrl)([
|
|
186
|
+
context.siteConfig.baseUrl,
|
|
187
|
+
options.routeBasePath,
|
|
188
|
+
feedConfigPath,
|
|
189
|
+
]),
|
|
190
|
+
title: feedConfigTitle,
|
|
191
|
+
},
|
|
192
|
+
});
|
|
193
|
+
});
|
|
194
|
+
return headTags;
|
|
195
|
+
}
|
|
196
|
+
exports.createFeedHtmlHeadTags = createFeedHtmlHeadTags;
|
package/lib/index.js
CHANGED
|
@@ -11,24 +11,52 @@ const tslib_1 = require("tslib");
|
|
|
11
11
|
const path_1 = tslib_1.__importDefault(require("path"));
|
|
12
12
|
const logger_1 = tslib_1.__importDefault(require("@docusaurus/logger"));
|
|
13
13
|
const utils_1 = require("@docusaurus/utils");
|
|
14
|
+
const utils_validation_1 = require("@docusaurus/utils-validation");
|
|
14
15
|
const blogUtils_1 = require("./blogUtils");
|
|
15
16
|
const footnoteIDFixer_1 = tslib_1.__importDefault(require("./remark/footnoteIDFixer"));
|
|
16
17
|
const translations_1 = require("./translations");
|
|
17
18
|
const feed_1 = require("./feed");
|
|
18
19
|
const routes_1 = require("./routes");
|
|
20
|
+
const PluginName = 'docusaurus-plugin-content-blog';
|
|
21
|
+
// TODO this is bad, we should have a better way to do this (new lifecycle?)
|
|
22
|
+
// The source to permalink is currently a mutable map passed to the mdx loader
|
|
23
|
+
// for link resolution
|
|
24
|
+
// see https://github.com/facebook/docusaurus/pull/10185
|
|
25
|
+
function createSourceToPermalinkHelper() {
|
|
26
|
+
const sourceToPermalink = new Map();
|
|
27
|
+
function computeSourceToPermalink(content) {
|
|
28
|
+
return new Map(content.blogPosts.map(({ metadata: { source, permalink } }) => [
|
|
29
|
+
source,
|
|
30
|
+
permalink,
|
|
31
|
+
]));
|
|
32
|
+
}
|
|
33
|
+
// Mutable map update :/
|
|
34
|
+
function update(content) {
|
|
35
|
+
sourceToPermalink.clear();
|
|
36
|
+
computeSourceToPermalink(content).forEach((value, key) => {
|
|
37
|
+
sourceToPermalink.set(key, value);
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
return { get: () => sourceToPermalink, update };
|
|
41
|
+
}
|
|
19
42
|
async function pluginContentBlog(context, options) {
|
|
20
43
|
const { siteDir, siteConfig, generatedFilesDir, localizationDir, i18n: { currentLocale }, } = context;
|
|
44
|
+
const router = siteConfig.future.experimental_router;
|
|
45
|
+
const isBlogFeedDisabledBecauseOfHashRouter = router === 'hash' && !!options.feedOptions.type;
|
|
46
|
+
if (isBlogFeedDisabledBecauseOfHashRouter) {
|
|
47
|
+
logger_1.default.warn(`${PluginName} feed feature does not support the Hash Router. Feeds won't be generated.`);
|
|
48
|
+
}
|
|
21
49
|
const { onBrokenMarkdownLinks, baseUrl } = siteConfig;
|
|
22
50
|
const contentPaths = {
|
|
23
51
|
contentPath: path_1.default.resolve(siteDir, options.path),
|
|
24
52
|
contentPathLocalized: (0, utils_1.getPluginI18nPath)({
|
|
25
53
|
localizationDir,
|
|
26
|
-
pluginName:
|
|
54
|
+
pluginName: PluginName,
|
|
27
55
|
pluginId: options.id,
|
|
28
56
|
}),
|
|
29
57
|
};
|
|
30
58
|
const pluginId = options.id ?? utils_1.DEFAULT_PLUGIN_ID;
|
|
31
|
-
const pluginDataDirRoot = path_1.default.join(generatedFilesDir,
|
|
59
|
+
const pluginDataDirRoot = path_1.default.join(generatedFilesDir, PluginName);
|
|
32
60
|
const dataDir = path_1.default.join(pluginDataDirRoot, pluginId);
|
|
33
61
|
// TODO Docusaurus v4 breaking change
|
|
34
62
|
// module aliasing should be automatic
|
|
@@ -38,12 +66,21 @@ async function pluginContentBlog(context, options) {
|
|
|
38
66
|
filePath: options.authorsMapPath,
|
|
39
67
|
contentPaths,
|
|
40
68
|
});
|
|
69
|
+
const sourceToPermalinkHelper = createSourceToPermalinkHelper();
|
|
41
70
|
return {
|
|
42
|
-
name:
|
|
71
|
+
name: PluginName,
|
|
43
72
|
getPathsToWatch() {
|
|
44
73
|
const { include } = options;
|
|
45
74
|
const contentMarkdownGlobs = (0, utils_1.getContentPathList)(contentPaths).flatMap((contentPath) => include.map((pattern) => `${contentPath}/${pattern}`));
|
|
46
|
-
|
|
75
|
+
const tagsFilePaths = (0, utils_validation_1.getTagsFilePathsToWatch)({
|
|
76
|
+
contentPaths,
|
|
77
|
+
tags: options.tags,
|
|
78
|
+
});
|
|
79
|
+
return [
|
|
80
|
+
authorsMapFilePath,
|
|
81
|
+
...tagsFilePaths,
|
|
82
|
+
...contentMarkdownGlobs,
|
|
83
|
+
].filter(Boolean);
|
|
47
84
|
},
|
|
48
85
|
getTranslationFiles() {
|
|
49
86
|
return (0, translations_1.getTranslationFiles)(options);
|
|
@@ -111,6 +148,7 @@ async function pluginContentBlog(context, options) {
|
|
|
111
148
|
};
|
|
112
149
|
},
|
|
113
150
|
async contentLoaded({ content, actions }) {
|
|
151
|
+
sourceToPermalinkHelper.update(content);
|
|
114
152
|
await (0, routes_1.createAllRoutes)({
|
|
115
153
|
baseUrl,
|
|
116
154
|
content,
|
|
@@ -122,21 +160,66 @@ async function pluginContentBlog(context, options) {
|
|
|
122
160
|
translateContent({ content, translationFiles }) {
|
|
123
161
|
return (0, translations_1.translateContent)(content, translationFiles);
|
|
124
162
|
},
|
|
125
|
-
configureWebpack(
|
|
163
|
+
configureWebpack() {
|
|
126
164
|
const { admonitions, rehypePlugins, remarkPlugins, truncateMarker, beforeDefaultRemarkPlugins, beforeDefaultRehypePlugins, } = options;
|
|
127
|
-
const markdownLoaderOptions = {
|
|
128
|
-
siteDir,
|
|
129
|
-
contentPaths,
|
|
130
|
-
truncateMarker,
|
|
131
|
-
sourceToPermalink: (0, blogUtils_1.getSourceToPermalink)(content.blogPosts),
|
|
132
|
-
onBrokenMarkdownLink: (brokenMarkdownLink) => {
|
|
133
|
-
if (onBrokenMarkdownLinks === 'ignore') {
|
|
134
|
-
return;
|
|
135
|
-
}
|
|
136
|
-
logger_1.default.report(onBrokenMarkdownLinks) `Blog markdown link couldn't be resolved: (url=${brokenMarkdownLink.link}) in path=${brokenMarkdownLink.filePath}`;
|
|
137
|
-
},
|
|
138
|
-
};
|
|
139
165
|
const contentDirs = (0, utils_1.getContentPathList)(contentPaths);
|
|
166
|
+
function createMDXLoader() {
|
|
167
|
+
const loaderOptions = {
|
|
168
|
+
admonitions,
|
|
169
|
+
remarkPlugins,
|
|
170
|
+
rehypePlugins,
|
|
171
|
+
beforeDefaultRemarkPlugins: [
|
|
172
|
+
footnoteIDFixer_1.default,
|
|
173
|
+
...beforeDefaultRemarkPlugins,
|
|
174
|
+
],
|
|
175
|
+
beforeDefaultRehypePlugins,
|
|
176
|
+
staticDirs: siteConfig.staticDirectories.map((dir) => path_1.default.resolve(siteDir, dir)),
|
|
177
|
+
siteDir,
|
|
178
|
+
isMDXPartial: (0, utils_1.createAbsoluteFilePathMatcher)(options.exclude, contentDirs),
|
|
179
|
+
metadataPath: (mdxPath) => {
|
|
180
|
+
// Note that metadataPath must be the same/in-sync as
|
|
181
|
+
// the path from createData for each MDX.
|
|
182
|
+
const aliasedPath = (0, utils_1.aliasedSitePath)(mdxPath, siteDir);
|
|
183
|
+
return path_1.default.join(dataDir, `${(0, utils_1.docuHash)(aliasedPath)}.json`);
|
|
184
|
+
},
|
|
185
|
+
// For blog posts a title in markdown is always removed
|
|
186
|
+
// Blog posts title are rendered separately
|
|
187
|
+
removeContentTitle: true,
|
|
188
|
+
// Assets allow to convert some relative images paths to
|
|
189
|
+
// require() calls
|
|
190
|
+
// @ts-expect-error: TODO fix typing issue
|
|
191
|
+
createAssets: ({ frontMatter, metadata, }) => ({
|
|
192
|
+
image: frontMatter.image,
|
|
193
|
+
authorsImageUrls: metadata.authors.map((author) => author.imageURL),
|
|
194
|
+
}),
|
|
195
|
+
markdownConfig: siteConfig.markdown,
|
|
196
|
+
resolveMarkdownLink: ({ linkPathname, sourceFilePath }) => {
|
|
197
|
+
const permalink = (0, utils_1.resolveMarkdownLinkPathname)(linkPathname, {
|
|
198
|
+
sourceFilePath,
|
|
199
|
+
sourceToPermalink: sourceToPermalinkHelper.get(),
|
|
200
|
+
siteDir,
|
|
201
|
+
contentPaths,
|
|
202
|
+
});
|
|
203
|
+
if (permalink === null) {
|
|
204
|
+
logger_1.default.report(onBrokenMarkdownLinks) `Blog markdown link couldn't be resolved: (url=${linkPathname}) in source file path=${sourceFilePath}`;
|
|
205
|
+
}
|
|
206
|
+
return permalink;
|
|
207
|
+
},
|
|
208
|
+
};
|
|
209
|
+
return {
|
|
210
|
+
loader: require.resolve('@docusaurus/mdx-loader'),
|
|
211
|
+
options: loaderOptions,
|
|
212
|
+
};
|
|
213
|
+
}
|
|
214
|
+
function createBlogMarkdownLoader() {
|
|
215
|
+
const loaderOptions = {
|
|
216
|
+
truncateMarker,
|
|
217
|
+
};
|
|
218
|
+
return {
|
|
219
|
+
loader: path_1.default.resolve(__dirname, './markdownLoader.js'),
|
|
220
|
+
options: loaderOptions,
|
|
221
|
+
};
|
|
222
|
+
}
|
|
140
223
|
return {
|
|
141
224
|
resolve: {
|
|
142
225
|
alias: {
|
|
@@ -150,59 +233,20 @@ async function pluginContentBlog(context, options) {
|
|
|
150
233
|
include: contentDirs
|
|
151
234
|
// Trailing slash is important, see https://github.com/facebook/docusaurus/pull/3970
|
|
152
235
|
.map(utils_1.addTrailingPathSeparator),
|
|
153
|
-
use: [
|
|
154
|
-
{
|
|
155
|
-
loader: require.resolve('@docusaurus/mdx-loader'),
|
|
156
|
-
options: {
|
|
157
|
-
admonitions,
|
|
158
|
-
remarkPlugins,
|
|
159
|
-
rehypePlugins,
|
|
160
|
-
beforeDefaultRemarkPlugins: [
|
|
161
|
-
footnoteIDFixer_1.default,
|
|
162
|
-
...beforeDefaultRemarkPlugins,
|
|
163
|
-
],
|
|
164
|
-
beforeDefaultRehypePlugins,
|
|
165
|
-
staticDirs: siteConfig.staticDirectories.map((dir) => path_1.default.resolve(siteDir, dir)),
|
|
166
|
-
siteDir,
|
|
167
|
-
isMDXPartial: (0, utils_1.createAbsoluteFilePathMatcher)(options.exclude, contentDirs),
|
|
168
|
-
metadataPath: (mdxPath) => {
|
|
169
|
-
// Note that metadataPath must be the same/in-sync as
|
|
170
|
-
// the path from createData for each MDX.
|
|
171
|
-
const aliasedPath = (0, utils_1.aliasedSitePath)(mdxPath, siteDir);
|
|
172
|
-
return path_1.default.join(dataDir, `${(0, utils_1.docuHash)(aliasedPath)}.json`);
|
|
173
|
-
},
|
|
174
|
-
// For blog posts a title in markdown is always removed
|
|
175
|
-
// Blog posts title are rendered separately
|
|
176
|
-
removeContentTitle: true,
|
|
177
|
-
// Assets allow to convert some relative images paths to
|
|
178
|
-
// require() calls
|
|
179
|
-
createAssets: ({ frontMatter, metadata, }) => ({
|
|
180
|
-
image: frontMatter.image,
|
|
181
|
-
authorsImageUrls: metadata.authors.map((author) => author.imageURL),
|
|
182
|
-
}),
|
|
183
|
-
markdownConfig: siteConfig.markdown,
|
|
184
|
-
},
|
|
185
|
-
},
|
|
186
|
-
{
|
|
187
|
-
loader: path_1.default.resolve(__dirname, './markdownLoader.js'),
|
|
188
|
-
options: markdownLoaderOptions,
|
|
189
|
-
},
|
|
190
|
-
].filter(Boolean),
|
|
236
|
+
use: [createMDXLoader(), createBlogMarkdownLoader()],
|
|
191
237
|
},
|
|
192
238
|
],
|
|
193
239
|
},
|
|
194
240
|
};
|
|
195
241
|
},
|
|
196
242
|
async postBuild({ outDir, content }) {
|
|
197
|
-
if (!
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
const { blogPosts } = content;
|
|
201
|
-
if (!blogPosts.length) {
|
|
243
|
+
if (!content.blogPosts.length ||
|
|
244
|
+
!options.feedOptions.type ||
|
|
245
|
+
isBlogFeedDisabledBecauseOfHashRouter) {
|
|
202
246
|
return;
|
|
203
247
|
}
|
|
204
248
|
await (0, feed_1.createBlogFeedFiles)({
|
|
205
|
-
blogPosts,
|
|
249
|
+
blogPosts: content.blogPosts,
|
|
206
250
|
options,
|
|
207
251
|
outDir,
|
|
208
252
|
siteConfig,
|
|
@@ -210,48 +254,12 @@ async function pluginContentBlog(context, options) {
|
|
|
210
254
|
});
|
|
211
255
|
},
|
|
212
256
|
injectHtmlTags({ content }) {
|
|
213
|
-
if (!content.blogPosts.length ||
|
|
257
|
+
if (!content.blogPosts.length ||
|
|
258
|
+
!options.feedOptions.type ||
|
|
259
|
+
isBlogFeedDisabledBecauseOfHashRouter) {
|
|
214
260
|
return {};
|
|
215
261
|
}
|
|
216
|
-
|
|
217
|
-
const feedTitle = options.feedOptions.title ?? context.siteConfig.title;
|
|
218
|
-
const feedsConfig = {
|
|
219
|
-
rss: {
|
|
220
|
-
type: 'application/rss+xml',
|
|
221
|
-
path: 'rss.xml',
|
|
222
|
-
title: `${feedTitle} RSS Feed`,
|
|
223
|
-
},
|
|
224
|
-
atom: {
|
|
225
|
-
type: 'application/atom+xml',
|
|
226
|
-
path: 'atom.xml',
|
|
227
|
-
title: `${feedTitle} Atom Feed`,
|
|
228
|
-
},
|
|
229
|
-
json: {
|
|
230
|
-
type: 'application/json',
|
|
231
|
-
path: 'feed.json',
|
|
232
|
-
title: `${feedTitle} JSON Feed`,
|
|
233
|
-
},
|
|
234
|
-
};
|
|
235
|
-
const headTags = [];
|
|
236
|
-
feedTypes.forEach((feedType) => {
|
|
237
|
-
const { type, path: feedConfigPath, title: feedConfigTitle, } = feedsConfig[feedType];
|
|
238
|
-
headTags.push({
|
|
239
|
-
tagName: 'link',
|
|
240
|
-
attributes: {
|
|
241
|
-
rel: 'alternate',
|
|
242
|
-
type,
|
|
243
|
-
href: (0, utils_1.normalizeUrl)([
|
|
244
|
-
baseUrl,
|
|
245
|
-
options.routeBasePath,
|
|
246
|
-
feedConfigPath,
|
|
247
|
-
]),
|
|
248
|
-
title: feedConfigTitle,
|
|
249
|
-
},
|
|
250
|
-
});
|
|
251
|
-
});
|
|
252
|
-
return {
|
|
253
|
-
headTags,
|
|
254
|
-
};
|
|
262
|
+
return { headTags: (0, feed_1.createFeedHtmlHeadTags)({ context, options }) };
|
|
255
263
|
},
|
|
256
264
|
};
|
|
257
265
|
}
|
package/lib/markdownLoader.js
CHANGED
|
@@ -8,20 +8,16 @@
|
|
|
8
8
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
9
|
const blogUtils_1 = require("./blogUtils");
|
|
10
10
|
function markdownLoader(source) {
|
|
11
|
-
const filePath = this.resourcePath;
|
|
12
11
|
const fileString = source;
|
|
13
12
|
const callback = this.async();
|
|
14
13
|
const markdownLoaderOptions = this.getOptions();
|
|
15
14
|
// Linkify blog posts
|
|
16
|
-
let finalContent =
|
|
17
|
-
fileString,
|
|
18
|
-
filePath,
|
|
19
|
-
...markdownLoaderOptions,
|
|
20
|
-
});
|
|
15
|
+
let finalContent = fileString;
|
|
21
16
|
// Truncate content if requested (e.g: file.md?truncated=true).
|
|
22
17
|
const truncated = this.resourceQuery
|
|
23
18
|
? !!new URLSearchParams(this.resourceQuery.slice(1)).get('truncated')
|
|
24
19
|
: undefined;
|
|
20
|
+
// TODO truncate with the AST instead of the string ?
|
|
25
21
|
if (truncated) {
|
|
26
22
|
finalContent = (0, blogUtils_1.truncate)(finalContent, markdownLoaderOptions.truncateMarker);
|
|
27
23
|
}
|
package/lib/options.js
CHANGED
|
@@ -42,6 +42,8 @@ exports.DEFAULT_OPTIONS = {
|
|
|
42
42
|
showLastUpdateTime: false,
|
|
43
43
|
showLastUpdateAuthor: false,
|
|
44
44
|
processBlogPosts: async () => undefined,
|
|
45
|
+
onInlineTags: 'warn',
|
|
46
|
+
tags: undefined,
|
|
45
47
|
};
|
|
46
48
|
const PluginOptionSchema = utils_validation_1.Joi.object({
|
|
47
49
|
path: utils_validation_1.Joi.string().default(exports.DEFAULT_OPTIONS.path),
|
|
@@ -111,6 +113,13 @@ const PluginOptionSchema = utils_validation_1.Joi.object({
|
|
|
111
113
|
processBlogPosts: utils_validation_1.Joi.function()
|
|
112
114
|
.optional()
|
|
113
115
|
.default(() => exports.DEFAULT_OPTIONS.processBlogPosts),
|
|
116
|
+
onInlineTags: utils_validation_1.Joi.string()
|
|
117
|
+
.equal('ignore', 'log', 'warn', 'throw')
|
|
118
|
+
.default(exports.DEFAULT_OPTIONS.onInlineTags),
|
|
119
|
+
tags: utils_validation_1.Joi.string()
|
|
120
|
+
.disallow('')
|
|
121
|
+
.allow(null, false)
|
|
122
|
+
.default(() => exports.DEFAULT_OPTIONS.tags),
|
|
114
123
|
}).default(exports.DEFAULT_OPTIONS);
|
|
115
124
|
function validateOptions({ validate, options, }) {
|
|
116
125
|
const validatedOptions = validate(PluginOptionSchema, options);
|
package/lib/props.js
CHANGED
|
@@ -7,6 +7,7 @@ function toTagsProp({ blogTags }) {
|
|
|
7
7
|
.map((tag) => ({
|
|
8
8
|
label: tag.label,
|
|
9
9
|
permalink: tag.permalink,
|
|
10
|
+
description: tag.description,
|
|
10
11
|
count: tag.items.length,
|
|
11
12
|
}));
|
|
12
13
|
}
|
|
@@ -15,6 +16,7 @@ function toTagProp({ blogTagsListPath, tag, }) {
|
|
|
15
16
|
return {
|
|
16
17
|
label: tag.label,
|
|
17
18
|
permalink: tag.permalink,
|
|
19
|
+
description: tag.description,
|
|
18
20
|
allTagsPath: blogTagsListPath,
|
|
19
21
|
count: tag.items.length,
|
|
20
22
|
unlisted: tag.unlisted,
|
package/lib/types.d.ts
CHANGED
|
@@ -4,15 +4,8 @@
|
|
|
4
4
|
* This source code is licensed under the MIT license found in the
|
|
5
5
|
* LICENSE file in the root directory of this source tree.
|
|
6
6
|
*/
|
|
7
|
-
import type {
|
|
7
|
+
import type { ContentPaths } from '@docusaurus/utils';
|
|
8
8
|
export type BlogContentPaths = ContentPaths;
|
|
9
|
-
export type BlogBrokenMarkdownLink = BrokenMarkdownLink<BlogContentPaths>;
|
|
10
9
|
export type BlogMarkdownLoaderOptions = {
|
|
11
|
-
siteDir: string;
|
|
12
|
-
contentPaths: BlogContentPaths;
|
|
13
10
|
truncateMarker: RegExp;
|
|
14
|
-
sourceToPermalink: {
|
|
15
|
-
[aliasedPath: string]: string;
|
|
16
|
-
};
|
|
17
|
-
onBrokenMarkdownLink: (brokenMarkdownLink: BlogBrokenMarkdownLink) => void;
|
|
18
11
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@docusaurus/plugin-content-blog",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.4.0",
|
|
4
4
|
"description": "Blog plugin for Docusaurus.",
|
|
5
5
|
"main": "lib/index.js",
|
|
6
6
|
"types": "src/plugin-content-blog.d.ts",
|
|
@@ -31,13 +31,13 @@
|
|
|
31
31
|
},
|
|
32
32
|
"license": "MIT",
|
|
33
33
|
"dependencies": {
|
|
34
|
-
"@docusaurus/core": "3.
|
|
35
|
-
"@docusaurus/logger": "3.
|
|
36
|
-
"@docusaurus/mdx-loader": "3.
|
|
37
|
-
"@docusaurus/types": "3.
|
|
38
|
-
"@docusaurus/utils": "3.
|
|
39
|
-
"@docusaurus/utils-common": "3.
|
|
40
|
-
"@docusaurus/utils-validation": "3.
|
|
34
|
+
"@docusaurus/core": "3.4.0",
|
|
35
|
+
"@docusaurus/logger": "3.4.0",
|
|
36
|
+
"@docusaurus/mdx-loader": "3.4.0",
|
|
37
|
+
"@docusaurus/types": "3.4.0",
|
|
38
|
+
"@docusaurus/utils": "3.4.0",
|
|
39
|
+
"@docusaurus/utils-common": "3.4.0",
|
|
40
|
+
"@docusaurus/utils-validation": "3.4.0",
|
|
41
41
|
"cheerio": "^1.0.0-rc.12",
|
|
42
42
|
"feed": "^4.2.2",
|
|
43
43
|
"fs-extra": "^11.1.1",
|
|
@@ -59,5 +59,5 @@
|
|
|
59
59
|
"devDependencies": {
|
|
60
60
|
"@total-typescript/shoehorn": "^0.1.2"
|
|
61
61
|
},
|
|
62
|
-
"gitHead": "
|
|
62
|
+
"gitHead": "49e9a2143274a8dd795659b417b470bc42abbd6e"
|
|
63
63
|
}
|