mirror of
https://github.com/facebook/docusaurus.git
synced 2025-05-21 13:06:58 +02:00
feat(v2): add meta RSS/Atom feed links to head (#2000)
Co-authored-by: Endi <endiliey@gmail.com> * feat(v2): add meta RSS/Atom feed links to head * refactor(v2): use new API * Better typing * fix typing
This commit is contained in:
parent
2297ae9f57
commit
3caff0d221
2 changed files with 77 additions and 10 deletions
|
@ -17,6 +17,7 @@ import {
|
||||||
BlogItemsToModules,
|
BlogItemsToModules,
|
||||||
TagsModule,
|
TagsModule,
|
||||||
BlogPaginated,
|
BlogPaginated,
|
||||||
|
FeedType,
|
||||||
} from './types';
|
} from './types';
|
||||||
import {
|
import {
|
||||||
LoadContext,
|
LoadContext,
|
||||||
|
@ -24,6 +25,7 @@ import {
|
||||||
ConfigureWebpackUtils,
|
ConfigureWebpackUtils,
|
||||||
Props,
|
Props,
|
||||||
Plugin,
|
Plugin,
|
||||||
|
HtmlTags,
|
||||||
} from '@docusaurus/types';
|
} from '@docusaurus/types';
|
||||||
import {Configuration, Loader} from 'webpack';
|
import {Configuration, Loader} from 'webpack';
|
||||||
import {generateBlogFeed, generateBlogPosts} from './blogUtils';
|
import {generateBlogFeed, generateBlogPosts} from './blogUtils';
|
||||||
|
@ -42,6 +44,26 @@ const DEFAULT_OPTIONS: PluginOptions = {
|
||||||
truncateMarker: /<!--\s*(truncate)\s*-->/, // string or regex
|
truncateMarker: /<!--\s*(truncate)\s*-->/, // string or regex
|
||||||
};
|
};
|
||||||
|
|
||||||
|
function assertFeedTypes(val: any): asserts val is FeedType {
|
||||||
|
if (typeof val !== 'string' && !['rss', 'atom', 'all'].includes(val)) {
|
||||||
|
throw new Error(
|
||||||
|
`Invalid feedOptions type: ${val}. It must be either 'rss', 'atom', or 'all'`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const getFeedTypes = (type?: FeedType) => {
|
||||||
|
assertFeedTypes(type);
|
||||||
|
let feedTypes: ('rss' | 'atom')[] = [];
|
||||||
|
|
||||||
|
if (type === 'all') {
|
||||||
|
feedTypes = ['rss', 'atom'];
|
||||||
|
} else {
|
||||||
|
feedTypes.push(type);
|
||||||
|
}
|
||||||
|
return feedTypes;
|
||||||
|
};
|
||||||
|
|
||||||
export default function pluginContentBlog(
|
export default function pluginContentBlog(
|
||||||
context: LoadContext,
|
context: LoadContext,
|
||||||
opts: Partial<PluginOptions>,
|
opts: Partial<PluginOptions>,
|
||||||
|
@ -389,19 +411,13 @@ export default function pluginContentBlog(
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const {
|
|
||||||
feedOptions: {type: feedType},
|
|
||||||
} = options;
|
|
||||||
const feed = await generateBlogFeed(context, options);
|
const feed = await generateBlogFeed(context, options);
|
||||||
|
|
||||||
if (!feed) {
|
if (!feed) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
let feedTypes = [];
|
|
||||||
if (feedType === 'all') {
|
const feedTypes = getFeedTypes(options.feedOptions?.type);
|
||||||
feedTypes = ['rss', 'atom'];
|
|
||||||
} else {
|
|
||||||
feedTypes.push(feedType);
|
|
||||||
}
|
|
||||||
|
|
||||||
await Promise.all(
|
await Promise.all(
|
||||||
feedTypes.map(feedType => {
|
feedTypes.map(feedType => {
|
||||||
|
@ -419,5 +435,54 @@ export default function pluginContentBlog(
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
injectHtmlTags() {
|
||||||
|
if (!options.feedOptions) {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
const feedTypes = getFeedTypes(options.feedOptions?.type);
|
||||||
|
const {
|
||||||
|
siteConfig: {title},
|
||||||
|
baseUrl,
|
||||||
|
} = context;
|
||||||
|
const feedsConfig = {
|
||||||
|
rss: {
|
||||||
|
type: 'application/rss+xml',
|
||||||
|
path: 'blog/rss.xml',
|
||||||
|
title: `${title} Blog RSS Feed`,
|
||||||
|
},
|
||||||
|
atom: {
|
||||||
|
type: 'application/atom+xml',
|
||||||
|
path: 'blog/atom.xml',
|
||||||
|
title: `${title} Blog Atom Feed`,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
const headTags: HtmlTags = [];
|
||||||
|
|
||||||
|
feedTypes.map(feedType => {
|
||||||
|
const feedConfig = feedsConfig[feedType] || {};
|
||||||
|
|
||||||
|
if (!feedsConfig) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const {type, path, title} = feedConfig;
|
||||||
|
|
||||||
|
headTags.push({
|
||||||
|
tagName: 'link',
|
||||||
|
attributes: {
|
||||||
|
rel: 'alternate',
|
||||||
|
type,
|
||||||
|
href: normalizeUrl([baseUrl, path]),
|
||||||
|
title,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
return {
|
||||||
|
headTags,
|
||||||
|
};
|
||||||
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,6 +17,8 @@ export interface DateLink {
|
||||||
link: string;
|
link: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export type FeedType = 'rss' | 'atom' | 'all';
|
||||||
|
|
||||||
export interface PluginOptions {
|
export interface PluginOptions {
|
||||||
path: string;
|
path: string;
|
||||||
routeBasePath: string;
|
routeBasePath: string;
|
||||||
|
@ -30,7 +32,7 @@ export interface PluginOptions {
|
||||||
rehypePlugins: string[];
|
rehypePlugins: string[];
|
||||||
truncateMarker: RegExp | string;
|
truncateMarker: RegExp | string;
|
||||||
feedOptions?: {
|
feedOptions?: {
|
||||||
type: 'rss' | 'atom' | 'all';
|
type: FeedType;
|
||||||
title?: string;
|
title?: string;
|
||||||
description?: string;
|
description?: string;
|
||||||
copyright: string;
|
copyright: string;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue