@rspress/plugin-rss 2.0.16 → 2.0.18

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/dist/index.d.ts CHANGED
@@ -111,7 +111,10 @@ export declare function getFeedFileType(type: FeedOutputType): {
111
111
  getContent: (feed: Feed) => string;
112
112
  };
113
113
 
114
- export declare function getOutputInfo({ id, output }: Pick<FeedChannel, 'id' | 'output'>, { siteUrl, output: globalOutput, }: Pick<PluginRssOptions, 'output' | 'siteUrl'>): ResolvedOutput;
114
+ export declare function getOutputInfo({ id, output }: Pick<FeedChannel, 'id' | 'output'>, { siteUrl, output: globalOutput, }: {
115
+ siteUrl: string;
116
+ output?: PluginRssOptions['output'];
117
+ }): ResolvedOutput;
115
118
 
116
119
  /**
117
120
  * feed information attached in `PageIndexInfo['feeds']` array
@@ -130,7 +133,7 @@ export declare const PluginComponents: {
130
133
 
131
134
  export declare const PluginName = "@rspress/plugin-rss";
132
135
 
133
- export declare function pluginRss(pluginRssOptions: PluginRssOptions): RspressPlugin;
136
+ export declare function pluginRss(pluginRssOptions?: PluginRssOptions): RspressPlugin;
134
137
 
135
138
  /**
136
139
  * plugin options for `pluginRss`
@@ -138,9 +141,9 @@ export declare function pluginRss(pluginRssOptions: PluginRssOptions): RspressPl
138
141
  export declare interface PluginRssOptions {
139
142
  /**
140
143
  * site url of this rspress site. it will be used in feed files and feed link.
141
- * @requires
144
+ * @default rspress `siteOrigin` config with `base`, or `base` when `siteOrigin` is not configured
142
145
  */
143
- siteUrl: string;
146
+ siteUrl?: string;
144
147
  /**
145
148
  * Feed options for each rss. If array is given, this plugin will produce multiple feed files.
146
149
  * @default { id: 'blog', test: '/blog/' }
package/dist/index.js CHANGED
@@ -1,9 +1,9 @@
1
1
  import { resolve } from "node:url";
2
2
  import { promises } from "node:fs";
3
3
  import node_path from "node:path";
4
- import { getIconUrlPath } from "@rspress/core";
4
+ import { getIconUrlPath, withBase, withSiteOrigin } from "@rspress/core";
5
5
  import { Feed } from "feed";
6
- import * as __rspack_external_node_path_c5b9b54f from "node:path";
6
+ import * as __rspack_external_node_path_806ed179 from "node:path";
7
7
  function notNullish(n) {
8
8
  return null != n;
9
9
  }
@@ -28,7 +28,7 @@ function sortByDate(l, r) {
28
28
  return (r ? r.getTime() : 0) - (l ? l.getTime() : 0);
29
29
  }
30
30
  async function writeFile(path, content) {
31
- const dir = __rspack_external_node_path_c5b9b54f.dirname(path);
31
+ const dir = __rspack_external_node_path_806ed179.dirname(path);
32
32
  await promises.mkdir(dir, {
33
33
  mode: 493,
34
34
  recursive: true
@@ -138,6 +138,9 @@ function getFeedFileType(type) {
138
138
  };
139
139
  }
140
140
  }
141
+ function ensureTrailingSlash(url) {
142
+ return url.endsWith('/') ? url : `${url}/`;
143
+ }
141
144
  async function renderFeedContent(feed, channel, output) {
142
145
  const content = output.getContent(feed);
143
146
  if (!output.transform) return content;
@@ -152,7 +155,7 @@ function getOutputInfo({ id, output }, { siteUrl, output: globalOutput }) {
152
155
  const { extension, mime, getContent } = getFeedFileType(type);
153
156
  const filename = output?.filename || `${id}.${extension}`;
154
157
  const dir = output?.dir || globalOutput?.dir || 'rss';
155
- const publicPath = output?.publicPath || globalOutput?.publicPath || siteUrl;
158
+ const publicPath = ensureTrailingSlash(output?.publicPath || globalOutput?.publicPath || siteUrl);
156
159
  const url = [
157
160
  publicPath,
158
161
  `${dir}/`,
@@ -175,7 +178,7 @@ function getOutputInfo({ id, output }, { siteUrl, output: globalOutput }) {
175
178
  class FeedsSet {
176
179
  feeds = [];
177
180
  feedsMapById = Object.create(null);
178
- set({ feed, output, siteUrl }, config) {
181
+ set({ feed, output }, config, siteUrl) {
179
182
  this.feeds = (Array.isArray(feed) ? feed : [
180
183
  {
181
184
  ...getDefaultFeedOption(),
@@ -204,6 +207,27 @@ class FeedsSet {
204
207
  return this.feeds.slice(0);
205
208
  }
206
209
  }
210
+ function plugin_rss_ensureTrailingSlash(url) {
211
+ return url.endsWith('/') ? url : `${url}/`;
212
+ }
213
+ function normalizeSiteUrl(siteUrl) {
214
+ try {
215
+ const url = new URL(siteUrl);
216
+ url.pathname = plugin_rss_ensureTrailingSlash(url.pathname);
217
+ return url.href;
218
+ } catch {
219
+ throw new Error('[plugin-rss] `siteUrl` must be a valid absolute URL with protocol, such as `https://example.com/base/`.');
220
+ }
221
+ }
222
+ function getSiteUrl(siteUrl, config) {
223
+ if (siteUrl) return normalizeSiteUrl(siteUrl);
224
+ const base = withBase('/', config.base ?? '/');
225
+ try {
226
+ return config.siteOrigin ? withSiteOrigin(base, config.siteOrigin) : base;
227
+ } catch {
228
+ throw new Error('[plugin-rss] `siteOrigin` in rspress.config.ts must be a valid absolute URL origin with protocol, such as `https://example.com`.');
229
+ }
230
+ }
207
231
  async function getRssItems(feeds, page, siteUrl, htmlContent) {
208
232
  return Promise.all(feeds.filter((options)=>testPage(options.test, page)).map(async (options)=>{
209
233
  const after = options.item || ((feed)=>feed);
@@ -214,9 +238,10 @@ async function getRssItems(feeds, page, siteUrl, htmlContent) {
214
238
  };
215
239
  }));
216
240
  }
217
- function pluginRss(pluginRssOptions) {
241
+ function pluginRss(pluginRssOptions = {}) {
218
242
  const feedsSet = new FeedsSet();
219
243
  let _pagesForRss = null;
244
+ let _siteUrl = '';
220
245
  return {
221
246
  name: PluginName,
222
247
  globalUIComponents: Object.values(PluginComponents),
@@ -228,7 +253,8 @@ function pluginRss(pluginRssOptions) {
228
253
  const enableSSG = Boolean((config.ssg || config.llms) ?? true);
229
254
  if (!enableSSG) throw new Error("[plugin-rss] RSS plugin requires SSG to be enabled. Please set `ssg: true` in your rspress.config.ts or remove the RSS plugin.");
230
255
  _pagesForRss = new Map();
231
- feedsSet.set(pluginRssOptions, config);
256
+ _siteUrl = getSiteUrl(pluginRssOptions.siteUrl, config);
257
+ feedsSet.set(pluginRssOptions, config, _siteUrl);
232
258
  },
233
259
  async extendPageData (pageData) {
234
260
  if (!_pagesForRss) return;
@@ -258,7 +284,7 @@ function pluginRss(pluginRssOptions) {
258
284
  const htmlPath = node_path.resolve(outDir, routePathToHtmlPath(routePath));
259
285
  const htmlFile = await readFile(htmlPath);
260
286
  const htmlContent = htmlFile ? extractHtmlContent(htmlFile) : null;
261
- const items = await getRssItems(channels.map((id)=>feedsSet.get(id)), page, pluginRssOptions.siteUrl, htmlContent);
287
+ const items = await getRssItems(channels.map((id)=>feedsSet.get(id)), page, _siteUrl, htmlContent);
262
288
  for (const { channel, ...item } of items){
263
289
  feeds[channel] = feeds[channel] || new Feed(createFeed(feedsSet.get(channel), config));
264
290
  feeds[channel].addItem(item);
@@ -272,6 +298,7 @@ function pluginRss(pluginRssOptions) {
272
298
  await writeFile(path, await renderFeedContent(feed, feedChannel, output));
273
299
  }
274
300
  _pagesForRss = null;
301
+ _siteUrl = '';
275
302
  }
276
303
  };
277
304
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rspress/plugin-rss",
3
- "version": "2.0.16",
3
+ "version": "2.0.18",
4
4
  "description": "A plugin for rss generation for rspress",
5
5
  "bugs": "https://github.com/web-infra-dev/rspress/issues",
6
6
  "repository": {
@@ -28,7 +28,7 @@
28
28
  "feed": "^5.2.1"
29
29
  },
30
30
  "devDependencies": {
31
- "@rslib/core": "0.23.0",
31
+ "@rslib/core": "0.23.2",
32
32
  "@types/node": "^22.8.1",
33
33
  "@types/react": "^19.2.17",
34
34
  "react": "^19.2.7",