diff --git a/apps/docs/docs/widgets/rss-feed/index.tsx b/apps/docs/docs/widgets/rss-feed/index.tsx index 3c2026337..9903b5f19 100644 --- a/apps/docs/docs/widgets/rss-feed/index.tsx +++ b/apps/docs/docs/widgets/rss-feed/index.tsx @@ -42,6 +42,12 @@ export const rssFeedWidget: WidgetDefinition = { values: "1-50", defaultValue: "5", }, + { + name: "Description max length", + description: "Maximum number of characters to keep from the feed description", + values: "1-5000", + defaultValue: "250", + }, { name: "Amount posts limit", description: "Maximum number of posts to show", diff --git a/packages/api/src/router/widgets/rssFeed.ts b/packages/api/src/router/widgets/rssFeed.ts index 87c49fca0..999cc5475 100644 --- a/packages/api/src/router/widgets/rssFeed.ts +++ b/packages/api/src/router/widgets/rssFeed.ts @@ -28,6 +28,7 @@ const redactFeedFailureMessage = (message: string) => message.replace(/https?:\/ const feedsInput = z.object({ urls: z.array(z.string()).max(100), maximumAmountPosts: z.number(), + descriptionMaxLength: z.number().int().min(1).max(5000).default(250), }); export const rssFeedRouter = createTRPCRouter({ @@ -43,6 +44,7 @@ export const rssFeedRouter = createTRPCRouter({ const innerHandler = rssFeedsRequestHandler.handler({ url, count: input.maximumAmountPosts, + descriptionMaxLength: input.descriptionMaxLength, }); return await innerHandler.getDataAsync(); }), diff --git a/packages/request-handler/src/rss-feeds.ts b/packages/request-handler/src/rss-feeds.ts index 3809d9692..fca695339 100644 --- a/packages/request-handler/src/rss-feeds.ts +++ b/packages/request-handler/src/rss-feeds.ts @@ -11,10 +11,11 @@ const logger = createLogger({ module: "rssFeedsRequestHandler" }); export const rssFeedsRequestHandler = createWidgetRequestHandler({ // Authorized editors can supply arbitrary URLs, so keep this cache process-local and bounded. - async requestAsync(input: { url: string; count: number }, signal) { + async requestAsync(input: { url: string; count: number; descriptionMaxLength: number }, signal) { const result = (await extract( input.url, { + descriptionMaxLen: input.descriptionMaxLength, getExtraEntryFields: (feedEntry) => { const media = attemptGetImageFromEntry(input.url, feedEntry); if (!media) { diff --git a/packages/translation/src/lang/en.json b/packages/translation/src/lang/en.json index 6aeed451f..991b96405 100644 --- a/packages/translation/src/lang/en.json +++ b/packages/translation/src/lang/en.json @@ -4480,6 +4480,10 @@ "textLinesClamp": { "label": "Description line clamp" }, + "descriptionMaxLength": { + "label": "Description max length", + "description": "Maximum number of characters to keep from the feed description" + }, "maximumAmountPosts": { "label": "Amount posts limit" }, diff --git a/packages/widgets/src/rssFeed/component.tsx b/packages/widgets/src/rssFeed/component.tsx index 158fbd06e..1113ff623 100644 --- a/packages/widgets/src/rssFeed/component.tsx +++ b/packages/widgets/src/rssFeed/component.tsx @@ -47,6 +47,8 @@ export default function RssFeed({ options, width, height, displayMode }: WidgetC const feed = useLiveFeed({ urls: options.feedUrls, maximumAmountPosts: typeof options.maximumAmountPosts === "number" ? options.maximumAmountPosts : 100, + descriptionMaxLength: + typeof options.descriptionMaxLength === "number" ? options.descriptionMaxLength : 250, }); const board = useRequiredBoard(); diff --git a/packages/widgets/src/rssFeed/index.ts b/packages/widgets/src/rssFeed/index.ts index abf728aa0..450b8f619 100644 --- a/packages/widgets/src/rssFeed/index.ts +++ b/packages/widgets/src/rssFeed/index.ts @@ -18,6 +18,7 @@ export const { definition, componentLoader } = createWidgetDefinition("rssFeed", widgetQueryInputMatches(input, { urls: scope.options.feedUrls, maximumAmountPosts: scope.options.maximumAmountPosts, + descriptionMaxLength: scope.options.descriptionMaxLength, }), refetchInterval: null, errors: { @@ -39,6 +40,10 @@ export const { definition, componentLoader } = createWidgetDefinition("rssFeed", defaultValue: 5, validate: z.number().min(1).max(50), }), + descriptionMaxLength: factory.number({ + defaultValue: 250, + validate: z.number().int().min(1).max(5000), + }), maximumAmountPosts: factory.number({ defaultValue: 100, validate: z.number().min(1).max(9999),