@docusaurus/plugin-content-blog 2.0.0-beta.16 → 2.0.0-beta.19
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/authors.d.ts +3 -1
- package/lib/authors.js +14 -6
- package/lib/blogUtils.d.ts +5 -3
- package/lib/blogUtils.js +21 -19
- package/lib/feed.d.ts +3 -3
- package/lib/feed.js +16 -17
- package/lib/{blogFrontMatter.d.ts → frontMatter.d.ts} +3 -1
- package/lib/{blogFrontMatter.js → frontMatter.js} +0 -0
- package/lib/index.d.ts +3 -4
- package/lib/index.js +50 -58
- package/lib/markdownLoader.js +1 -1
- package/lib/options.d.ts +10 -0
- package/lib/{pluginOptionSchema.js → options.js} +9 -4
- package/lib/remark/footnoteIDFixer.d.ts +14 -0
- package/lib/remark/footnoteIDFixer.js +29 -0
- package/lib/translations.d.ts +4 -5
- package/lib/translations.js +4 -4
- package/lib/types.d.ts +4 -73
- package/package.json +13 -12
- package/src/authors.ts +29 -17
- package/src/blogUtils.ts +30 -22
- package/src/deps.d.ts +1 -1
- package/src/feed.ts +53 -56
- package/src/{blogFrontMatter.ts → frontMatter.ts} +3 -3
- package/src/index.ts +74 -98
- package/src/markdownLoader.ts +1 -1
- package/src/{pluginOptionSchema.ts → options.ts} +16 -4
- package/src/plugin-content-blog.d.ts +408 -97
- package/src/remark/footnoteIDFixer.ts +29 -0
- package/src/translations.ts +14 -9
- package/src/types.ts +2 -94
- package/lib/pluginOptionSchema.d.ts +0 -10
|
@@ -6,188 +6,495 @@
|
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
8
|
declare module '@docusaurus/plugin-content-blog' {
|
|
9
|
-
import type {
|
|
10
|
-
import type {FrontMatterTag} from '@docusaurus/utils';
|
|
9
|
+
import type {MDXOptions} from '@docusaurus/mdx-loader';
|
|
10
|
+
import type {FrontMatterTag, Tag} from '@docusaurus/utils';
|
|
11
|
+
import type {Plugin, LoadContext} from '@docusaurus/types';
|
|
11
12
|
import type {Overwrite} from 'utility-types';
|
|
12
13
|
|
|
13
|
-
export
|
|
14
|
+
export type Assets = {
|
|
15
|
+
/**
|
|
16
|
+
* If `metadata.image` is a collocated image path, this entry will be the
|
|
17
|
+
* bundler-generated image path. Otherwise, it's empty, and the image URL
|
|
18
|
+
* should be accessed through `frontMatter.image`.
|
|
19
|
+
*/
|
|
14
20
|
image?: string;
|
|
15
|
-
|
|
16
|
-
|
|
21
|
+
/**
|
|
22
|
+
* Array where each item is 1-1 correlated with the `metadata.authors` array
|
|
23
|
+
* so that client can render the correct author images. If the author's
|
|
24
|
+
* image is a local file path, the slot will be filled with the bundler-
|
|
25
|
+
* generated image path; otherwise, it's empty, and the author's image URL
|
|
26
|
+
* should be accessed through `authors.imageURL`.
|
|
27
|
+
*/
|
|
28
|
+
authorsImageUrls: (string | undefined)[];
|
|
29
|
+
};
|
|
17
30
|
|
|
18
|
-
|
|
19
|
-
|
|
31
|
+
export type Author = {
|
|
32
|
+
/**
|
|
33
|
+
* If `name` doesn't exist, an `imageURL` is expected.
|
|
34
|
+
*/
|
|
20
35
|
name?: string;
|
|
36
|
+
/**
|
|
37
|
+
* The image path could be collocated, in which case
|
|
38
|
+
* `metadata.assets.authorsImageUrls` should be used instead. If `imageURL`
|
|
39
|
+
* doesn't exist, a `name` is expected.
|
|
40
|
+
*/
|
|
21
41
|
imageURL?: string;
|
|
42
|
+
/**
|
|
43
|
+
* Used to generate the author's link.
|
|
44
|
+
*/
|
|
22
45
|
url?: string;
|
|
46
|
+
/**
|
|
47
|
+
* Used as a subtitle for the author, e.g. "maintainer of Docusaurus"
|
|
48
|
+
*/
|
|
23
49
|
title?: string;
|
|
24
|
-
|
|
50
|
+
/**
|
|
51
|
+
* Mainly used for RSS feeds; if `url` doesn't exist, `email` can be used
|
|
52
|
+
* to generate a fallback `mailto:` URL.
|
|
53
|
+
*/
|
|
54
|
+
email?: string;
|
|
55
|
+
/**
|
|
56
|
+
* Unknown keys are allowed, so that we can pass custom fields to authors,
|
|
57
|
+
* e.g., `twitter`.
|
|
58
|
+
*/
|
|
59
|
+
[key: string]: unknown;
|
|
60
|
+
};
|
|
25
61
|
|
|
62
|
+
/**
|
|
63
|
+
* Everything is partial/unnormalized, because front matter is always
|
|
64
|
+
* preserved as-is. Default values will be applied when generating metadata
|
|
65
|
+
*/
|
|
26
66
|
export type BlogPostFrontMatter = {
|
|
67
|
+
/**
|
|
68
|
+
* @deprecated Use `slug` instead.
|
|
69
|
+
*/
|
|
27
70
|
id?: string;
|
|
71
|
+
/**
|
|
72
|
+
* Will override the default title collected from h1 heading.
|
|
73
|
+
* @see {@link BlogPostMetadata.title}
|
|
74
|
+
*/
|
|
28
75
|
title?: string;
|
|
76
|
+
/**
|
|
77
|
+
* Will override the default excerpt.
|
|
78
|
+
* @see {@link BlogPostMetadata.description}
|
|
79
|
+
*/
|
|
29
80
|
description?: string;
|
|
81
|
+
/**
|
|
82
|
+
* Front matter tags, unnormalized.
|
|
83
|
+
* @see {@link BlogPostMetadata.tags}
|
|
84
|
+
*/
|
|
30
85
|
tags?: FrontMatterTag[];
|
|
86
|
+
/** Custom slug appended after `/<baseUrl>/<routeBasePath>/` */
|
|
31
87
|
slug?: string;
|
|
88
|
+
/**
|
|
89
|
+
* Marks the post as draft and excludes it from the production build.
|
|
90
|
+
*/
|
|
32
91
|
draft?: boolean;
|
|
33
|
-
|
|
34
|
-
|
|
92
|
+
/**
|
|
93
|
+
* Will override the default publish date inferred from git/filename. Yaml
|
|
94
|
+
* only converts standard yyyy-MM-dd format to dates, so this may stay as a
|
|
95
|
+
* plain string.
|
|
96
|
+
* @see {@link BlogPostMetadata.date}
|
|
97
|
+
*/
|
|
98
|
+
date?: Date | string;
|
|
99
|
+
/**
|
|
100
|
+
* Authors, unnormalized.
|
|
101
|
+
* @see {@link BlogPostMetadata.authors}
|
|
102
|
+
*/
|
|
35
103
|
authors?: BlogPostFrontMatterAuthors;
|
|
36
|
-
|
|
37
|
-
|
|
104
|
+
/**
|
|
105
|
+
* To be deprecated
|
|
106
|
+
* @see {@link BlogPostFrontMatterAuthor.name}
|
|
107
|
+
*/
|
|
38
108
|
author?: string;
|
|
109
|
+
/**
|
|
110
|
+
* To be deprecated
|
|
111
|
+
* @see {@link BlogPostFrontMatterAuthor.title}
|
|
112
|
+
*/
|
|
39
113
|
author_title?: string;
|
|
114
|
+
/**
|
|
115
|
+
* To be deprecated
|
|
116
|
+
* @see {@link BlogPostFrontMatterAuthor.url}
|
|
117
|
+
*/
|
|
40
118
|
author_url?: string;
|
|
119
|
+
/**
|
|
120
|
+
* To be deprecated
|
|
121
|
+
* @see {@link BlogPostFrontMatterAuthor.imageURL}
|
|
122
|
+
*/
|
|
41
123
|
author_image_url?: string;
|
|
42
124
|
|
|
43
|
-
/** @deprecated */
|
|
125
|
+
/** @deprecated v1 legacy */
|
|
44
126
|
authorTitle?: string;
|
|
45
|
-
/** @deprecated */
|
|
127
|
+
/** @deprecated v1 legacy */
|
|
46
128
|
authorURL?: string;
|
|
47
|
-
/** @deprecated */
|
|
129
|
+
/** @deprecated v1 legacy */
|
|
48
130
|
authorImageURL?: string;
|
|
49
131
|
|
|
132
|
+
/** Used in the head meta. Should use `assets.image` in priority. */
|
|
50
133
|
image?: string;
|
|
134
|
+
/** Used in the head meta. */
|
|
51
135
|
keywords?: string[];
|
|
136
|
+
/** Hide the right TOC. */
|
|
52
137
|
hide_table_of_contents?: boolean;
|
|
138
|
+
/**
|
|
139
|
+
* Minimum TOC heading level. Must be between 2 and 6 and lower or equal to
|
|
140
|
+
* the max value.
|
|
141
|
+
*/
|
|
53
142
|
toc_min_heading_level?: number;
|
|
143
|
+
/** Maximum TOC heading level. Must be between 2 and 6. */
|
|
54
144
|
toc_max_heading_level?: number;
|
|
55
145
|
};
|
|
56
146
|
|
|
57
|
-
export type BlogPostFrontMatterAuthor =
|
|
147
|
+
export type BlogPostFrontMatterAuthor = Author & {
|
|
148
|
+
/**
|
|
149
|
+
* Will be normalized into the `imageURL` prop.
|
|
150
|
+
*/
|
|
151
|
+
image_url?: string;
|
|
152
|
+
/**
|
|
153
|
+
* References an existing author in the authors map.
|
|
154
|
+
*/
|
|
58
155
|
key?: string;
|
|
59
|
-
name?: string;
|
|
60
|
-
imageURL?: string;
|
|
61
|
-
url?: string;
|
|
62
|
-
title?: string;
|
|
63
156
|
};
|
|
64
157
|
|
|
65
|
-
|
|
158
|
+
/**
|
|
159
|
+
* Blog post authors can be declared in front matter as a string key
|
|
160
|
+
* (referencing an author in authors map), an object (partially overriding the
|
|
161
|
+
* data in authors map, or a completely new author), or an array of a mix of
|
|
162
|
+
* both.
|
|
163
|
+
*/
|
|
66
164
|
export type BlogPostFrontMatterAuthors =
|
|
67
165
|
| string
|
|
68
166
|
| BlogPostFrontMatterAuthor
|
|
69
167
|
| (string | BlogPostFrontMatterAuthor)[];
|
|
70
168
|
|
|
169
|
+
export type BlogPostMetadata = {
|
|
170
|
+
/** Path to the Markdown source, with `@site` alias. */
|
|
171
|
+
readonly source: string;
|
|
172
|
+
/**
|
|
173
|
+
* Used to generate the page h1 heading, tab title, and pagination title.
|
|
174
|
+
*/
|
|
175
|
+
readonly title: string;
|
|
176
|
+
/**
|
|
177
|
+
* The publish date of the post. On client side, this will be serialized
|
|
178
|
+
* into a string.
|
|
179
|
+
*/
|
|
180
|
+
readonly date: Date;
|
|
181
|
+
/**
|
|
182
|
+
* Publish date formatted according to the locale, so that the client can
|
|
183
|
+
* render the date regardless of the existence of `Intl.DateTimeFormat`.
|
|
184
|
+
*/
|
|
185
|
+
readonly formattedDate: string;
|
|
186
|
+
/** Full link including base URL. */
|
|
187
|
+
readonly permalink: string;
|
|
188
|
+
/**
|
|
189
|
+
* Description used in the meta. Could be an empty string (empty content)
|
|
190
|
+
*/
|
|
191
|
+
readonly description: string;
|
|
192
|
+
/**
|
|
193
|
+
* Absolute URL to the editing page of the post. Undefined if the post
|
|
194
|
+
* shouldn't be edited.
|
|
195
|
+
*/
|
|
196
|
+
readonly editUrl?: string;
|
|
197
|
+
/**
|
|
198
|
+
* Reading time in minutes calculated based on word count.
|
|
199
|
+
*/
|
|
200
|
+
readonly readingTime?: number;
|
|
201
|
+
/**
|
|
202
|
+
* Whether the truncate marker exists in the post's content.
|
|
203
|
+
*/
|
|
204
|
+
readonly truncated?: boolean;
|
|
205
|
+
/**
|
|
206
|
+
* Used in pagination. Generated after the other metadata, so not readonly.
|
|
207
|
+
* Content is just a subset of another post's metadata.
|
|
208
|
+
*/
|
|
209
|
+
nextItem?: {readonly title: string; readonly permalink: string};
|
|
210
|
+
/**
|
|
211
|
+
* Used in pagination. Generated after the other metadata, so not readonly.
|
|
212
|
+
* Content is just a subset of another post's metadata.
|
|
213
|
+
*/
|
|
214
|
+
prevItem?: {readonly title: string; readonly permalink: string};
|
|
215
|
+
/**
|
|
216
|
+
* Author metadata, normalized. Should be used in joint with
|
|
217
|
+
* `assets.authorsImageUrls` on client side.
|
|
218
|
+
*/
|
|
219
|
+
readonly authors: Author[];
|
|
220
|
+
/** Front matter, as-is. */
|
|
221
|
+
readonly frontMatter: BlogPostFrontMatter & {[key: string]: unknown};
|
|
222
|
+
/** Tags, normalized. */
|
|
223
|
+
readonly tags: Tag[];
|
|
224
|
+
};
|
|
225
|
+
/**
|
|
226
|
+
* @returns The edit URL that's directly plugged into metadata.
|
|
227
|
+
*/
|
|
71
228
|
export type EditUrlFunction = (editUrlParams: {
|
|
229
|
+
/**
|
|
230
|
+
* The root content directory containing this post file, relative to the
|
|
231
|
+
* site path. Usually the same as `options.path` but can be localized
|
|
232
|
+
*/
|
|
72
233
|
blogDirPath: string;
|
|
234
|
+
/** Path to this post file, relative to `blogDirPath`. */
|
|
73
235
|
blogPath: string;
|
|
236
|
+
/** @see {@link BlogPostMetadata.permalink} */
|
|
74
237
|
permalink: string;
|
|
238
|
+
/** Locale name. */
|
|
75
239
|
locale: string;
|
|
76
240
|
}) => string | undefined;
|
|
77
241
|
|
|
78
242
|
export type FeedType = 'rss' | 'atom' | 'json';
|
|
243
|
+
/**
|
|
244
|
+
* Normalized feed options used within code.
|
|
245
|
+
*/
|
|
79
246
|
export type FeedOptions = {
|
|
247
|
+
/** If `null`, no feed is generated. */
|
|
80
248
|
type?: FeedType[] | null;
|
|
249
|
+
/** Title of generated feed. */
|
|
81
250
|
title?: string;
|
|
251
|
+
/** Description of generated feed. */
|
|
82
252
|
description?: string;
|
|
253
|
+
/** Copyright notice. Required because the feed library marked it that. */
|
|
83
254
|
copyright: string;
|
|
255
|
+
/** Language of the feed. */
|
|
84
256
|
language?: string;
|
|
85
257
|
};
|
|
86
|
-
// Feed options, as provided by user config
|
|
87
|
-
export type UserFeedOptions = Overwrite<
|
|
88
|
-
Partial<FeedOptions>,
|
|
89
|
-
{type?: FeedOptions['type'] | 'all'} // Handle the type: "all" shortcut
|
|
90
|
-
>;
|
|
91
258
|
|
|
92
|
-
|
|
259
|
+
/**
|
|
260
|
+
* Duplicate from ngryman/reading-time to keep stability of API.
|
|
261
|
+
*/
|
|
93
262
|
type ReadingTimeOptions = {
|
|
94
263
|
wordsPerMinute?: number;
|
|
264
|
+
/**
|
|
265
|
+
* @param char The character to be matched.
|
|
266
|
+
* @returns `true` if this character is a word bound.
|
|
267
|
+
*/
|
|
95
268
|
wordBound?: (char: string) => boolean;
|
|
96
269
|
};
|
|
97
270
|
|
|
271
|
+
/**
|
|
272
|
+
* Represents the default reading time implementation.
|
|
273
|
+
* @returns The reading time directly plugged into metadata.
|
|
274
|
+
*/
|
|
98
275
|
export type ReadingTimeFunction = (params: {
|
|
276
|
+
/** Markdown content. */
|
|
99
277
|
content: string;
|
|
100
|
-
|
|
278
|
+
/** Front matter. */
|
|
279
|
+
frontMatter?: BlogPostFrontMatter & {[key: string]: unknown};
|
|
280
|
+
/** Options accepted by ngryman/reading-time. */
|
|
101
281
|
options?: ReadingTimeOptions;
|
|
102
282
|
}) => number;
|
|
103
283
|
|
|
284
|
+
/**
|
|
285
|
+
* @returns The reading time directly plugged into metadata. `undefined` to
|
|
286
|
+
* hide reading time for a specific post.
|
|
287
|
+
*/
|
|
104
288
|
export type ReadingTimeFunctionOption = (
|
|
289
|
+
/**
|
|
290
|
+
* The `options` is not provided by the caller; the user can inject their
|
|
291
|
+
* own option values into `defaultReadingTime`
|
|
292
|
+
*/
|
|
105
293
|
params: Required<Omit<Parameters<ReadingTimeFunction>[0], 'options'>> & {
|
|
294
|
+
/**
|
|
295
|
+
* The default reading time implementation from ngryman/reading-time.
|
|
296
|
+
*/
|
|
106
297
|
defaultReadingTime: ReadingTimeFunction;
|
|
107
298
|
},
|
|
108
299
|
) => number | undefined;
|
|
109
|
-
|
|
110
|
-
|
|
300
|
+
/**
|
|
301
|
+
* Plugin options after normalization.
|
|
302
|
+
*/
|
|
303
|
+
export type PluginOptions = MDXOptions & {
|
|
304
|
+
/** Plugin ID. */
|
|
111
305
|
id?: string;
|
|
306
|
+
/**
|
|
307
|
+
* Path to the blog content directory on the file system, relative to site
|
|
308
|
+
* directory.
|
|
309
|
+
*/
|
|
112
310
|
path: string;
|
|
311
|
+
/**
|
|
312
|
+
* URL route for the blog section of your site. **DO NOT** include a
|
|
313
|
+
* trailing slash. Use `/` to put the blog at root path.
|
|
314
|
+
*/
|
|
113
315
|
routeBasePath: string;
|
|
316
|
+
/**
|
|
317
|
+
* URL route for the tags section of your blog. Will be appended to
|
|
318
|
+
* `routeBasePath`. **DO NOT** include a trailing slash.
|
|
319
|
+
*/
|
|
114
320
|
tagsBasePath: string;
|
|
321
|
+
/**
|
|
322
|
+
* URL route for the archive section of your blog. Will be appended to
|
|
323
|
+
* `routeBasePath`. **DO NOT** include a trailing slash. Use `null` to
|
|
324
|
+
* disable generation of archive.
|
|
325
|
+
*/
|
|
115
326
|
archiveBasePath: string | null;
|
|
327
|
+
/**
|
|
328
|
+
* Array of glob patterns matching Markdown files to be built, relative to
|
|
329
|
+
* the content path.
|
|
330
|
+
*/
|
|
116
331
|
include: string[];
|
|
332
|
+
/**
|
|
333
|
+
* Array of glob patterns matching Markdown files to be excluded. Serves as
|
|
334
|
+
* refinement based on the `include` option.
|
|
335
|
+
*/
|
|
117
336
|
exclude: string[];
|
|
337
|
+
/**
|
|
338
|
+
* Number of posts to show per page in the listing page. Use `'ALL'` to
|
|
339
|
+
* display all posts on one listing page.
|
|
340
|
+
*/
|
|
118
341
|
postsPerPage: number | 'ALL';
|
|
342
|
+
/** Root component of the blog listing page. */
|
|
119
343
|
blogListComponent: string;
|
|
344
|
+
/** Root component of each blog post page. */
|
|
120
345
|
blogPostComponent: string;
|
|
346
|
+
/** Root component of the tags list page. */
|
|
121
347
|
blogTagsListComponent: string;
|
|
348
|
+
/** Root component of the "posts containing tag" page. */
|
|
122
349
|
blogTagsPostsComponent: string;
|
|
350
|
+
/** Root component of the blog archive page. */
|
|
123
351
|
blogArchiveComponent: string;
|
|
352
|
+
/** Blog page title for better SEO. */
|
|
124
353
|
blogTitle: string;
|
|
354
|
+
/** Blog page meta description for better SEO. */
|
|
125
355
|
blogDescription: string;
|
|
356
|
+
/**
|
|
357
|
+
* Number of blog post elements to show in the blog sidebar. `'ALL'` to show
|
|
358
|
+
* all blog posts; `0` to disable.
|
|
359
|
+
*/
|
|
126
360
|
blogSidebarCount: number | 'ALL';
|
|
361
|
+
/** Title of the blog sidebar. */
|
|
127
362
|
blogSidebarTitle: string;
|
|
363
|
+
/** Truncate marker marking where the summary ends. */
|
|
128
364
|
truncateMarker: RegExp;
|
|
365
|
+
/** Show estimated reading time for the blog post. */
|
|
129
366
|
showReadingTime: boolean;
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
367
|
+
/** Blog feed. */
|
|
368
|
+
feedOptions: FeedOptions;
|
|
369
|
+
/**
|
|
370
|
+
* Base URL to edit your site. The final URL is computed by `editUrl +
|
|
371
|
+
* relativePostPath`. Using a function allows more nuanced control for each
|
|
372
|
+
* file. Omitting this variable entirely will disable edit links.
|
|
373
|
+
*/
|
|
137
374
|
editUrl?: string | EditUrlFunction;
|
|
375
|
+
/**
|
|
376
|
+
* The edit URL will target the localized file, instead of the original
|
|
377
|
+
* unlocalized file. Ignored when `editUrl` is a function.
|
|
378
|
+
*/
|
|
138
379
|
editLocalizedFiles?: boolean;
|
|
139
|
-
admonitions:
|
|
380
|
+
admonitions: {[key: string]: unknown};
|
|
381
|
+
/** Path to the authors map file, relative to the blog content directory. */
|
|
140
382
|
authorsMapPath: string;
|
|
383
|
+
/** A callback to customize the reading time number displayed. */
|
|
141
384
|
readingTime: ReadingTimeFunctionOption;
|
|
385
|
+
/** Governs the direction of blog post sorting. */
|
|
142
386
|
sortPosts: 'ascending' | 'descending';
|
|
143
387
|
};
|
|
144
|
-
|
|
388
|
+
|
|
389
|
+
/**
|
|
390
|
+
* Feed options, as provided by user config. `type` accepts `all` as shortcut
|
|
391
|
+
*/
|
|
392
|
+
export type UserFeedOptions = Overwrite<
|
|
393
|
+
Partial<FeedOptions>,
|
|
394
|
+
{
|
|
395
|
+
/** Type of feed to be generated. Use `null` to disable generation. */
|
|
396
|
+
type?: FeedOptions['type'] | 'all' | FeedType;
|
|
397
|
+
}
|
|
398
|
+
>;
|
|
399
|
+
/**
|
|
400
|
+
* Options as provided in the user config (before normalization)
|
|
401
|
+
*/
|
|
145
402
|
export type Options = Overwrite<
|
|
146
403
|
Partial<PluginOptions>,
|
|
147
|
-
{
|
|
404
|
+
{
|
|
405
|
+
/** Blog feed. */
|
|
406
|
+
feedOptions?: UserFeedOptions;
|
|
407
|
+
}
|
|
148
408
|
>;
|
|
409
|
+
|
|
410
|
+
export type BlogSidebar = {
|
|
411
|
+
title: string;
|
|
412
|
+
items: {title: string; permalink: string}[];
|
|
413
|
+
};
|
|
414
|
+
|
|
415
|
+
export type BlogContent = {
|
|
416
|
+
blogSidebarTitle: string;
|
|
417
|
+
blogPosts: BlogPost[];
|
|
418
|
+
blogListPaginated: BlogPaginated[];
|
|
419
|
+
blogTags: BlogTags;
|
|
420
|
+
blogTagsListPath: string;
|
|
421
|
+
};
|
|
422
|
+
|
|
423
|
+
export type BlogTags = {
|
|
424
|
+
[permalink: string]: BlogTag;
|
|
425
|
+
};
|
|
426
|
+
|
|
427
|
+
export type BlogTag = Tag & {
|
|
428
|
+
/** Blog post permalinks. */
|
|
429
|
+
items: string[];
|
|
430
|
+
pages: BlogPaginated[];
|
|
431
|
+
};
|
|
432
|
+
|
|
433
|
+
export type BlogPost = {
|
|
434
|
+
id: string;
|
|
435
|
+
metadata: BlogPostMetadata;
|
|
436
|
+
content: string;
|
|
437
|
+
};
|
|
438
|
+
|
|
439
|
+
export type BlogPaginatedMetadata = {
|
|
440
|
+
/** Title of the entire blog. */
|
|
441
|
+
readonly blogTitle: string;
|
|
442
|
+
/** Blog description. */
|
|
443
|
+
readonly blogDescription: string;
|
|
444
|
+
/** Permalink to the next list page. */
|
|
445
|
+
readonly nextPage?: string;
|
|
446
|
+
/** Permalink of the current page. */
|
|
447
|
+
readonly permalink: string;
|
|
448
|
+
/** Permalink to the previous list page. */
|
|
449
|
+
readonly previousPage?: string;
|
|
450
|
+
/** Index of the current page, 1-based. */
|
|
451
|
+
readonly page: number;
|
|
452
|
+
/** Posts displayed on each list page. */
|
|
453
|
+
readonly postsPerPage: number;
|
|
454
|
+
/** Total number of posts in the entire blog. */
|
|
455
|
+
readonly totalCount: number;
|
|
456
|
+
/** Total number of list pages. */
|
|
457
|
+
readonly totalPages: number;
|
|
458
|
+
};
|
|
459
|
+
|
|
460
|
+
export type BlogPaginated = {
|
|
461
|
+
metadata: BlogPaginatedMetadata;
|
|
462
|
+
/** Blog post permalinks. */
|
|
463
|
+
items: string[];
|
|
464
|
+
};
|
|
465
|
+
|
|
466
|
+
export default function pluginContentBlog(
|
|
467
|
+
context: LoadContext,
|
|
468
|
+
options: PluginOptions,
|
|
469
|
+
): Promise<Plugin<BlogContent>>;
|
|
149
470
|
}
|
|
150
471
|
|
|
151
472
|
declare module '@theme/BlogPostPage' {
|
|
152
|
-
import type {
|
|
153
|
-
import type {TOCItem} from '@docusaurus/types';
|
|
473
|
+
import type {LoadedMDXContent} from '@docusaurus/mdx-loader';
|
|
154
474
|
import type {
|
|
155
475
|
BlogPostFrontMatter,
|
|
156
|
-
|
|
476
|
+
BlogPostMetadata,
|
|
157
477
|
Assets,
|
|
478
|
+
BlogSidebar,
|
|
158
479
|
} from '@docusaurus/plugin-content-blog';
|
|
480
|
+
import type {Overwrite} from 'utility-types';
|
|
159
481
|
|
|
160
482
|
export type FrontMatter = BlogPostFrontMatter;
|
|
161
483
|
|
|
162
|
-
export type Metadata =
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
readonly readingTime?: number;
|
|
170
|
-
readonly truncated?: string;
|
|
171
|
-
readonly nextItem?: {readonly title: string; readonly permalink: string};
|
|
172
|
-
readonly prevItem?: {readonly title: string; readonly permalink: string};
|
|
173
|
-
readonly authors: Author[];
|
|
174
|
-
readonly frontMatter: FrontMatter & Record<string, unknown>;
|
|
175
|
-
readonly tags: readonly {
|
|
176
|
-
readonly label: string;
|
|
177
|
-
readonly permalink: string;
|
|
178
|
-
}[];
|
|
179
|
-
};
|
|
484
|
+
export type Metadata = Overwrite<
|
|
485
|
+
BlogPostMetadata,
|
|
486
|
+
{
|
|
487
|
+
/** The publish date of the post. Serialized from the `Date` object. */
|
|
488
|
+
date: string;
|
|
489
|
+
}
|
|
490
|
+
>;
|
|
180
491
|
|
|
181
|
-
export type Content =
|
|
182
|
-
readonly frontMatter: FrontMatter;
|
|
183
|
-
readonly assets: Assets;
|
|
184
|
-
readonly metadata: Metadata;
|
|
185
|
-
readonly toc: readonly TOCItem[];
|
|
186
|
-
(): JSX.Element;
|
|
187
|
-
};
|
|
492
|
+
export type Content = LoadedMDXContent<FrontMatter, Metadata, Assets>;
|
|
188
493
|
|
|
189
494
|
export interface Props {
|
|
495
|
+
/** Blog sidebar. */
|
|
190
496
|
readonly sidebar: BlogSidebar;
|
|
497
|
+
/** Content of this post as an MDX component, with useful metadata. */
|
|
191
498
|
readonly content: Content;
|
|
192
499
|
}
|
|
193
500
|
|
|
@@ -196,23 +503,20 @@ declare module '@theme/BlogPostPage' {
|
|
|
196
503
|
|
|
197
504
|
declare module '@theme/BlogListPage' {
|
|
198
505
|
import type {Content} from '@theme/BlogPostPage';
|
|
199
|
-
import type {
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
readonly blogDescription: string;
|
|
204
|
-
readonly nextPage?: string;
|
|
205
|
-
readonly page: number;
|
|
206
|
-
readonly permalink: string;
|
|
207
|
-
readonly postsPerPage: number;
|
|
208
|
-
readonly previousPage?: string;
|
|
209
|
-
readonly totalCount: number;
|
|
210
|
-
readonly totalPages: number;
|
|
211
|
-
};
|
|
506
|
+
import type {
|
|
507
|
+
BlogSidebar,
|
|
508
|
+
BlogPaginatedMetadata,
|
|
509
|
+
} from '@docusaurus/plugin-content-blog';
|
|
212
510
|
|
|
213
511
|
export interface Props {
|
|
512
|
+
/** Blog sidebar. */
|
|
214
513
|
readonly sidebar: BlogSidebar;
|
|
215
|
-
|
|
514
|
+
/** Metadata of the current listing page. */
|
|
515
|
+
readonly metadata: BlogPaginatedMetadata;
|
|
516
|
+
/**
|
|
517
|
+
* Array of blog posts included on this page. Every post's metadata is also
|
|
518
|
+
* available.
|
|
519
|
+
*/
|
|
216
520
|
readonly items: readonly {readonly content: Content}[];
|
|
217
521
|
}
|
|
218
522
|
|
|
@@ -220,34 +524,38 @@ declare module '@theme/BlogListPage' {
|
|
|
220
524
|
}
|
|
221
525
|
|
|
222
526
|
declare module '@theme/BlogTagsListPage' {
|
|
223
|
-
import type {BlogSidebar} from '@
|
|
224
|
-
|
|
225
|
-
export type Tag = {
|
|
226
|
-
permalink: string;
|
|
227
|
-
name: string;
|
|
228
|
-
count: number;
|
|
229
|
-
allTagsPath: string;
|
|
230
|
-
slug: string;
|
|
231
|
-
};
|
|
527
|
+
import type {BlogSidebar} from '@docusaurus/plugin-content-blog';
|
|
528
|
+
import type {TagsListItem} from '@docusaurus/utils';
|
|
232
529
|
|
|
233
530
|
export interface Props {
|
|
531
|
+
/** Blog sidebar. */
|
|
234
532
|
readonly sidebar: BlogSidebar;
|
|
235
|
-
|
|
533
|
+
/** All tags declared in this blog. */
|
|
534
|
+
readonly tags: TagsListItem[];
|
|
236
535
|
}
|
|
237
536
|
|
|
238
537
|
export default function BlogTagsListPage(props: Props): JSX.Element;
|
|
239
538
|
}
|
|
240
539
|
|
|
241
540
|
declare module '@theme/BlogTagsPostsPage' {
|
|
242
|
-
import type {
|
|
243
|
-
|
|
541
|
+
import type {
|
|
542
|
+
BlogSidebar,
|
|
543
|
+
BlogPaginatedMetadata,
|
|
544
|
+
} from '@docusaurus/plugin-content-blog';
|
|
244
545
|
import type {Content} from '@theme/BlogPostPage';
|
|
245
|
-
import type {
|
|
546
|
+
import type {TagModule} from '@docusaurus/utils';
|
|
246
547
|
|
|
247
548
|
export interface Props {
|
|
549
|
+
/** Blog sidebar. */
|
|
248
550
|
readonly sidebar: BlogSidebar;
|
|
249
|
-
|
|
250
|
-
readonly
|
|
551
|
+
/** Metadata of this tag. */
|
|
552
|
+
readonly tag: TagModule;
|
|
553
|
+
/** Looks exactly the same as the posts list page */
|
|
554
|
+
readonly listMetadata: BlogPaginatedMetadata;
|
|
555
|
+
/**
|
|
556
|
+
* Array of blog posts included on this page. Every post's metadata is also
|
|
557
|
+
* available.
|
|
558
|
+
*/
|
|
251
559
|
readonly items: readonly {readonly content: Content}[];
|
|
252
560
|
}
|
|
253
561
|
|
|
@@ -257,10 +565,13 @@ declare module '@theme/BlogTagsPostsPage' {
|
|
|
257
565
|
declare module '@theme/BlogArchivePage' {
|
|
258
566
|
import type {Content} from '@theme/BlogPostPage';
|
|
259
567
|
|
|
568
|
+
/** We may add extra metadata or prune some metadata from here */
|
|
260
569
|
export type ArchiveBlogPost = Content;
|
|
261
570
|
|
|
262
571
|
export interface Props {
|
|
572
|
+
/** The entirety of the blog's data. */
|
|
263
573
|
readonly archive: {
|
|
574
|
+
/** All posts. Can select any useful data/metadata to render. */
|
|
264
575
|
readonly blogPosts: readonly ArchiveBlogPost[];
|
|
265
576
|
};
|
|
266
577
|
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) Facebook, Inc. and its affiliates.
|
|
3
|
+
*
|
|
4
|
+
* This source code is licensed under the MIT license found in the
|
|
5
|
+
* LICENSE file in the root directory of this source tree.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import visit from 'unist-util-visit';
|
|
9
|
+
import {simpleHash} from '@docusaurus/utils';
|
|
10
|
+
import type {Transformer} from 'unified';
|
|
11
|
+
import type {FootnoteReference, FootnoteDefinition} from 'mdast';
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* In the blog list view, each post will be compiled separately. However, they
|
|
15
|
+
* may use the same footnote IDs. This leads to duplicated DOM IDs and inability
|
|
16
|
+
* to navigate to footnote references. This plugin fixes it by appending a
|
|
17
|
+
* unique hash to each reference/definition.
|
|
18
|
+
*/
|
|
19
|
+
export default function plugin(): Transformer {
|
|
20
|
+
return (root, vfile) => {
|
|
21
|
+
const suffix = `-${simpleHash(vfile.path!, 6)}`;
|
|
22
|
+
visit(root, 'footnoteReference', (node: FootnoteReference) => {
|
|
23
|
+
node.identifier += suffix;
|
|
24
|
+
});
|
|
25
|
+
visit(root, 'footnoteDefinition', (node: FootnoteDefinition) => {
|
|
26
|
+
node.identifier += suffix;
|
|
27
|
+
});
|
|
28
|
+
};
|
|
29
|
+
}
|