@docusaurus/plugin-content-blog 2.0.0-beta.15a2b59f9 → 2.0.0-beta.17

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.
Files changed (51) hide show
  1. package/lib/authors.d.ts +20 -0
  2. package/lib/authors.js +110 -0
  3. package/lib/blogFrontMatter.d.ts +1 -21
  4. package/lib/blogFrontMatter.js +31 -19
  5. package/lib/blogUtils.d.ts +24 -6
  6. package/lib/blogUtils.js +196 -143
  7. package/lib/feed.d.ts +15 -0
  8. package/lib/feed.js +99 -0
  9. package/lib/index.d.ts +4 -3
  10. package/lib/index.js +149 -163
  11. package/lib/markdownLoader.d.ts +3 -6
  12. package/lib/markdownLoader.js +5 -6
  13. package/lib/pluginOptionSchema.d.ts +3 -26
  14. package/lib/pluginOptionSchema.js +35 -10
  15. package/lib/translations.d.ts +11 -0
  16. package/lib/translations.js +53 -0
  17. package/lib/types.d.ts +10 -46
  18. package/package.json +21 -18
  19. package/src/authors.ts +153 -0
  20. package/src/blogFrontMatter.ts +44 -51
  21. package/src/blogUtils.ts +289 -195
  22. package/{types.d.ts → src/deps.d.ts} +0 -0
  23. package/src/feed.ts +170 -0
  24. package/src/index.ts +197 -194
  25. package/src/markdownLoader.ts +10 -15
  26. package/src/plugin-content-blog.d.ts +270 -0
  27. package/src/pluginOptionSchema.ts +41 -13
  28. package/src/translations.ts +64 -0
  29. package/src/types.ts +19 -53
  30. package/index.d.ts +0 -138
  31. package/lib/.tsbuildinfo +0 -1
  32. package/src/__tests__/__fixtures__/website/blog/2018-12-14-Happy-First-Birthday-Slash.md +0 -5
  33. package/src/__tests__/__fixtures__/website/blog/complex-slug.md +0 -7
  34. package/src/__tests__/__fixtures__/website/blog/date-matter.md +0 -5
  35. package/src/__tests__/__fixtures__/website/blog/draft.md +0 -6
  36. package/src/__tests__/__fixtures__/website/blog/heading-as-title.md +0 -5
  37. package/src/__tests__/__fixtures__/website/blog/simple-slug.md +0 -7
  38. package/src/__tests__/__fixtures__/website/blog-with-ref/2018-12-14-Happy-First-Birthday-Slash.md +0 -5
  39. package/src/__tests__/__fixtures__/website/blog-with-ref/post-with-broken-links.md +0 -11
  40. package/src/__tests__/__fixtures__/website/blog-with-ref/post.md +0 -5
  41. package/src/__tests__/__fixtures__/website/i18n/en/docusaurus-plugin-content-blog/2018-12-14-Happy-First-Birthday-Slash.md +0 -5
  42. package/src/__tests__/__fixtures__/website-blog-without-date/blog/no date.md +0 -1
  43. package/src/__tests__/__snapshots__/generateBlogFeed.test.ts.snap +0 -76
  44. package/src/__tests__/__snapshots__/linkify.test.ts.snap +0 -24
  45. package/src/__tests__/__snapshots__/pluginOptionSchema.test.ts.snap +0 -5
  46. package/src/__tests__/blogFrontMatter.test.ts +0 -317
  47. package/src/__tests__/generateBlogFeed.test.ts +0 -100
  48. package/src/__tests__/index.test.ts +0 -336
  49. package/src/__tests__/linkify.test.ts +0 -93
  50. package/src/__tests__/pluginOptionSchema.test.ts +0 -150
  51. package/tsconfig.json +0 -9
package/src/feed.ts ADDED
@@ -0,0 +1,170 @@
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 {Feed, type Author as FeedAuthor, type Item as FeedItem} from 'feed';
9
+ import type {BlogPost} from './types';
10
+ import {
11
+ normalizeUrl,
12
+ posixPath,
13
+ mapAsyncSequential,
14
+ readOutputHTMLFile,
15
+ } from '@docusaurus/utils';
16
+ import cheerio from 'cheerio';
17
+ import type {DocusaurusConfig} from '@docusaurus/types';
18
+ import path from 'path';
19
+ import fs from 'fs-extra';
20
+ import type {
21
+ FeedType,
22
+ PluginOptions,
23
+ Author,
24
+ } from '@docusaurus/plugin-content-blog';
25
+ import {blogPostContainerID} from '@docusaurus/utils-common';
26
+
27
+ async function generateBlogFeed({
28
+ blogPosts,
29
+ options,
30
+ siteConfig,
31
+ outDir,
32
+ }: {
33
+ blogPosts: BlogPost[];
34
+ options: PluginOptions;
35
+ siteConfig: DocusaurusConfig;
36
+ outDir: string;
37
+ }): Promise<Feed | null> {
38
+ if (!blogPosts.length) {
39
+ return null;
40
+ }
41
+
42
+ const {feedOptions, routeBasePath} = options;
43
+ const {url: siteUrl, baseUrl, title, favicon} = siteConfig;
44
+ const blogBaseUrl = normalizeUrl([siteUrl, baseUrl, routeBasePath]);
45
+
46
+ const updated = blogPosts[0] && blogPosts[0].metadata.date;
47
+
48
+ const feed = new Feed({
49
+ id: blogBaseUrl,
50
+ title: feedOptions.title || `${title} Blog`,
51
+ updated,
52
+ language: feedOptions.language,
53
+ link: blogBaseUrl,
54
+ description: feedOptions.description || `${siteConfig.title} Blog`,
55
+ favicon: favicon ? normalizeUrl([siteUrl, baseUrl, favicon]) : undefined,
56
+ copyright: feedOptions.copyright,
57
+ });
58
+
59
+ function toFeedAuthor(author: Author): FeedAuthor {
60
+ return {name: author.name, link: author.url, email: author.email};
61
+ }
62
+
63
+ await mapAsyncSequential(blogPosts, async (post) => {
64
+ const {
65
+ id,
66
+ metadata: {
67
+ title: metadataTitle,
68
+ permalink,
69
+ date,
70
+ description,
71
+ authors,
72
+ tags,
73
+ },
74
+ } = post;
75
+
76
+ const content = await readOutputHTMLFile(
77
+ permalink.replace(siteConfig.baseUrl, ''),
78
+ outDir,
79
+ siteConfig.trailingSlash,
80
+ );
81
+ const $ = cheerio.load(content);
82
+
83
+ const feedItem: FeedItem = {
84
+ title: metadataTitle,
85
+ id,
86
+ link: normalizeUrl([siteUrl, permalink]),
87
+ date,
88
+ description,
89
+ // Atom feed demands the "term", while other feeds use "name"
90
+ category: tags.map((tag) => ({name: tag.label, term: tag.label})),
91
+ content: $(`#${blogPostContainerID}`).html()!,
92
+ };
93
+
94
+ // json1() method takes the first item of authors array
95
+ // it causes an error when authors array is empty
96
+ const feedItemAuthors = authors.map(toFeedAuthor);
97
+ if (feedItemAuthors.length > 0) {
98
+ feedItem.author = feedItemAuthors;
99
+ }
100
+
101
+ feed.addItem(feedItem);
102
+ });
103
+
104
+ return feed;
105
+ }
106
+
107
+ async function createBlogFeedFile({
108
+ feed,
109
+ feedType,
110
+ generatePath,
111
+ }: {
112
+ feed: Feed;
113
+ feedType: FeedType;
114
+ generatePath: string;
115
+ }) {
116
+ const [feedContent, feedPath] = (() => {
117
+ switch (feedType) {
118
+ case 'rss':
119
+ return [feed.rss2(), 'rss.xml'];
120
+ case 'json':
121
+ return [feed.json1(), 'feed.json'];
122
+ case 'atom':
123
+ return [feed.atom1(), 'atom.xml'];
124
+ default:
125
+ throw new Error(`Feed type ${feedType} not supported.`);
126
+ }
127
+ })();
128
+ try {
129
+ await fs.outputFile(
130
+ posixPath(path.join(generatePath, feedPath)),
131
+ feedContent,
132
+ );
133
+ } catch (err) {
134
+ throw new Error(`Generating ${feedType} feed failed: ${err}.`);
135
+ }
136
+ }
137
+
138
+ export async function createBlogFeedFiles({
139
+ blogPosts,
140
+ options,
141
+ siteConfig,
142
+ outDir,
143
+ }: {
144
+ blogPosts: BlogPost[];
145
+ options: PluginOptions;
146
+ siteConfig: DocusaurusConfig;
147
+ outDir: string;
148
+ }): Promise<void> {
149
+ const feed = await generateBlogFeed({
150
+ blogPosts,
151
+ options,
152
+ siteConfig,
153
+ outDir,
154
+ });
155
+
156
+ const feedTypes = options.feedOptions.type;
157
+ if (!feed || !feedTypes) {
158
+ return;
159
+ }
160
+
161
+ await Promise.all(
162
+ feedTypes.map((feedType) =>
163
+ createBlogFeedFile({
164
+ feed,
165
+ feedType,
166
+ generatePath: path.join(outDir, options.routeBasePath),
167
+ }),
168
+ ),
169
+ );
170
+ }