Skip to content

Commit cf783ff

Browse files
committed
Improve RSS Feed Behavior
- `partial` now prefers an explicitly provided description if available - new `type` `metadata` will only use document metadata rather than infering descriptions Fixes #7290
1 parent 1322834 commit cf783ff

File tree

8 files changed

+81
-45
lines changed

8 files changed

+81
-45
lines changed

news/changelog-1.4.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,7 @@
124124
- ([#7634](https://github.com/quarto-dev/quarto-cli/issues/7634)): Use an explicit width to ensure default listing layout doesn't grow outside its desired boundss
125125
- ([#7345](https://github.com/quarto-dev/quarto-cli/issues/7345)): Improve display of categories in a table style listing
126126
- ([#7699](https://github.com/quarto-dev/quarto-cli/issues/7699)): Properly ignore non-HTML output for listings when project level renders render HTML and other formats (for example, a book of both HTML and PDF format)
127+
- ([#7290](https://github.com/quarto-dev/quarto-cli/issues/7290)): Add support for `feed:type` of `metadata`, which will use only explicitly provided description metadata when generating an RSS feed. Additionally, note that `partial` feed types will prefer to use an explicit description over the first paragraph, when a description is available.
127128

128129
## Websites
129130

src/project/types/website/listing/website-listing-feed.ts

Lines changed: 25 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -181,7 +181,7 @@ export async function createFeed(
181181
// The core feed file is generated 'staged' with placeholders for
182182
// content that should be replaced with rendered version of the content
183183
// from fully rendered documents.
184-
const stagedPath = feedPath(dir, stem, options.type === "full");
184+
const stagedPath = feedPath(dir, stem, options.type);
185185

186186
const feedFiles: string[] = [];
187187

@@ -220,7 +220,7 @@ export async function createFeed(
220220
file: feedPath(
221221
dir,
222222
`${stem}-${category.toLocaleLowerCase()}`,
223-
options.type === "full",
223+
options.type,
224224
),
225225
finalFile: finalRelPath,
226226
feedLink: absoluteUrl(siteUrl, finalRelPath),
@@ -293,7 +293,11 @@ export function completeStagedFeeds(
293293

294294
try {
295295
// Whether the staged file should be filled with full contents of the file
296-
const fullContents = feedFile.endsWith(kFullStagedExt);
296+
const type = feedFile.endsWith(kFullStagedExt)
297+
? "full"
298+
: feedFile.endsWith(kPartialStagedExt)
299+
? "partial"
300+
: "metadata";
297301

298302
// Read the staged file contents and replace any
299303
// content with the rendered version from the document
@@ -314,10 +318,14 @@ export function completeStagedFeeds(
314318
tag: "description",
315319
regex: kDescRegex,
316320
replaceValue: (rendered: RenderedContents) => {
317-
if (fullContents) {
321+
if (type === "full") {
318322
return `<![CDATA[ ${rendered.fullContents} ]]>`;
323+
} else if (type === "partial") {
324+
return `<![CDATA[ ${
325+
rendered.description || rendered.firstPara
326+
} ]]>`;
319327
} else {
320-
return `<![CDATA[ ${rendered.firstPara} ]]>`;
328+
return `<![CDATA[ ${rendered.description || ""} ]]>`;
321329
}
322330
},
323331
},
@@ -577,7 +585,8 @@ function addLinkTagToDocument(doc: Document, feed: FeedMetadata, path: string) {
577585
}
578586

579587
const kFullStagedExt = "feed-full-staged";
580-
const kPartialStageExt = "feed-partial-staged";
588+
const kPartialStagedExt = "feed-partial-staged";
589+
const kMetadataStagedExt = "feed-metadata-staged";
581590
const kFinalExt = "xml";
582591
const kStagedFileGlob = "*.feed-*-staged";
583592

@@ -597,8 +606,16 @@ function tagplaceholderRegex(tag: string) {
597606
return new RegExp(`<${tag}>{B4F502887207\:(.*?)}<\/${tag}>`, "gm");
598607
}
599608

600-
function feedPath(dir: string, stem: string, full: boolean) {
601-
const ext = full ? kFullStagedExt : kPartialStageExt;
609+
function feedPath(
610+
dir: string,
611+
stem: string,
612+
type: "full" | "partial" | "metadata",
613+
) {
614+
const ext = type === "full"
615+
? kFullStagedExt
616+
: type === "partial"
617+
? kPartialStagedExt
618+
: kMetadataStagedExt;
602619
const file = `${stem}.${ext}`;
603620
return join(dir, file);
604621
}

src/project/types/website/listing/website-listing-shared.ts

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -141,7 +141,7 @@ export type CategoryStyle =
141141
export interface ListingFeedOptions {
142142
[kTitle]?: string;
143143
[kItems]?: number;
144-
[kType]: "summary" | "full";
144+
[kType]: "partial" | "full" | "metadata";
145145
[kDescription]?: string;
146146
[kFieldCategories]?: string | string[];
147147
[kImage]?: string;
@@ -219,6 +219,7 @@ export interface ListingItem extends Record<string, unknown> {
219219

220220
export interface RenderedContents {
221221
title: string | undefined;
222+
description: string | undefined;
222223
firstPara: string | undefined;
223224
fullContents: string | undefined;
224225
previewImage: PreviewImage | undefined;
@@ -323,6 +324,16 @@ export function readRenderedContents(
323324
titleEl.remove();
324325
}
325326

327+
// Read the explicit description, if present
328+
let description = "";
329+
const descEl = doc.querySelector("meta[name='description']");
330+
if (descEl) {
331+
const descAttrVal = descEl.getAttribute("content");
332+
if (descAttrVal !== null) {
333+
description = descAttrVal;
334+
}
335+
}
336+
326337
// Remove any navigation elements from the content region
327338
const navEls = doc.querySelectorAll("nav");
328339
if (navEls) {
@@ -573,6 +584,7 @@ export function readRenderedContents(
573584

574585
return {
575586
title: titleText,
587+
description,
576588
fullContents,
577589
firstPara,
578590
previewImage: computePreviewImage(),

src/resources/editor/tools/vs-code.mjs

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -10317,11 +10317,12 @@ var require_yaml_intelligence_resources = __commonJS({
1031710317
type: {
1031810318
enum: [
1031910319
"full",
10320-
"partial"
10320+
"partial",
10321+
"metadata"
1032110322
],
1032210323
description: {
1032310324
short: "Whether to include full or partial content in the feed.",
10324-
long: "Whether to include full or partial content in the feed.\n\n- `full` (default): Include the complete content of the document in the feed.\n- `partial`: Include only the first paragraph of the document in the feed.\n"
10325+
long: "Whether to include full or partial content in the feed.\n\n- `full` (default): Include the complete content of the document in the feed.\n- `partial`: Include only the first paragraph of the document in the feed.\n- `metadata`: Use only the title, description, and other document metadata in the feed.\n"
1032510326
}
1032610327
},
1032710328
title: {
@@ -15239,7 +15240,7 @@ var require_yaml_intelligence_resources = __commonJS({
1523915240
description: "Options for controlling the display and behavior of Notebook previews."
1524015241
},
1524115242
{
15242-
"canonical-url": null,
15243+
name: "canonical-url",
1524315244
tags: {
1524415245
formats: [
1524515246
"$html-doc"
@@ -21283,6 +21284,10 @@ var require_yaml_intelligence_resources = __commonJS({
2128321284
"The style of document to render. Setting this to\n<code>notebook</code> will create additional notebook style\naffordances.",
2128421285
"Options for controlling the display and behavior of Notebook\npreviews.",
2128521286
"Whether to show a back button in the notebook preview.",
21287+
{
21288+
short: "Include a canonical link tag in website pages",
21289+
long: "Include a canonical link tag in website pages. You may pass either\n<code>true</code> to automatically generate a canonical link, or pass a\ncanonical url that you\u2019d like to have placed in the <code>href</code>\nattribute of the tag.\nCanonical links can only be generated for websites with a known\n<code>site-url</code>."
21290+
},
2128621291
"Automatically generate the contents of a page from a list of Quarto\ndocuments or other custom data.",
2128721292
"Mermaid diagram options",
2128821293
"The mermaid built-in theme to use.",
@@ -22352,11 +22357,7 @@ var require_yaml_intelligence_resources = __commonJS({
2235222357
},
2235322358
"Disambiguating year suffix in author-date styles (e.g.&nbsp;\u201Ca\u201D in \u201CDoe,\n1999a\u201D).",
2235422359
"Manuscript configuration",
22355-
"internal-schema-hack",
22356-
{
22357-
short: "Include a canonical link tag in website pages",
22358-
long: "Include a canonical link tag in website pages. You may pass either\n<code>true</code> to automatically generate a canonical link, or pass a\ncanonical url that you\u2019d like to have placed in the <code>href</code>\nattribute of the tag.\nCanonical links can only be generated for websites with a known\n<code>site-url</code>."
22359-
}
22360+
"internal-schema-hack"
2236022361
],
2236122362
"schema/external-schemas.yml": [
2236222363
{
@@ -22580,12 +22581,12 @@ var require_yaml_intelligence_resources = __commonJS({
2258022581
mermaid: "%%"
2258122582
},
2258222583
"handlers/mermaid/schema.yml": {
22583-
_internalId: 180143,
22584+
_internalId: 180637,
2258422585
type: "object",
2258522586
description: "be an object",
2258622587
properties: {
2258722588
"mermaid-format": {
22588-
_internalId: 180135,
22589+
_internalId: 180629,
2258922590
type: "enum",
2259022591
enum: [
2259122592
"png",
@@ -22601,7 +22602,7 @@ var require_yaml_intelligence_resources = __commonJS({
2260122602
exhaustiveCompletions: true
2260222603
},
2260322604
theme: {
22604-
_internalId: 180142,
22605+
_internalId: 180636,
2260522606
type: "anyOf",
2260622607
anyOf: [
2260722608
{

src/resources/editor/tools/yaml/web-worker.js

Lines changed: 12 additions & 11 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/resources/editor/tools/yaml/yaml-intelligence-resources.json

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -3289,11 +3289,12 @@
32893289
"type": {
32903290
"enum": [
32913291
"full",
3292-
"partial"
3292+
"partial",
3293+
"metadata"
32933294
],
32943295
"description": {
32953296
"short": "Whether to include full or partial content in the feed.",
3296-
"long": "Whether to include full or partial content in the feed.\n\n- `full` (default): Include the complete content of the document in the feed.\n- `partial`: Include only the first paragraph of the document in the feed.\n"
3297+
"long": "Whether to include full or partial content in the feed.\n\n- `full` (default): Include the complete content of the document in the feed.\n- `partial`: Include only the first paragraph of the document in the feed.\n- `metadata`: Use only the title, description, and other document metadata in the feed.\n"
32973298
}
32983299
},
32993300
"title": {
@@ -8211,7 +8212,7 @@
82118212
"description": "Options for controlling the display and behavior of Notebook previews."
82128213
},
82138214
{
8214-
"canonical-url": null,
8215+
"name": "canonical-url",
82158216
"tags": {
82168217
"formats": [
82178218
"$html-doc"
@@ -14255,6 +14256,10 @@
1425514256
"The style of document to render. Setting this to\n<code>notebook</code> will create additional notebook style\naffordances.",
1425614257
"Options for controlling the display and behavior of Notebook\npreviews.",
1425714258
"Whether to show a back button in the notebook preview.",
14259+
{
14260+
"short": "Include a canonical link tag in website pages",
14261+
"long": "Include a canonical link tag in website pages. You may pass either\n<code>true</code> to automatically generate a canonical link, or pass a\ncanonical url that you’d like to have placed in the <code>href</code>\nattribute of the tag.\nCanonical links can only be generated for websites with a known\n<code>site-url</code>."
14262+
},
1425814263
"Automatically generate the contents of a page from a list of Quarto\ndocuments or other custom data.",
1425914264
"Mermaid diagram options",
1426014265
"The mermaid built-in theme to use.",
@@ -15324,11 +15329,7 @@
1532415329
},
1532515330
"Disambiguating year suffix in author-date styles (e.g.&nbsp;“a” in “Doe,\n1999a”).",
1532615331
"Manuscript configuration",
15327-
"internal-schema-hack",
15328-
{
15329-
"short": "Include a canonical link tag in website pages",
15330-
"long": "Include a canonical link tag in website pages. You may pass either\n<code>true</code> to automatically generate a canonical link, or pass a\ncanonical url that you’d like to have placed in the <code>href</code>\nattribute of the tag.\nCanonical links can only be generated for websites with a known\n<code>site-url</code>."
15331-
}
15332+
"internal-schema-hack"
1533215333
],
1533315334
"schema/external-schemas.yml": [
1533415335
{
@@ -15552,12 +15553,12 @@
1555215553
"mermaid": "%%"
1555315554
},
1555415555
"handlers/mermaid/schema.yml": {
15555-
"_internalId": 180143,
15556+
"_internalId": 180637,
1555615557
"type": "object",
1555715558
"description": "be an object",
1555815559
"properties": {
1555915560
"mermaid-format": {
15560-
"_internalId": 180135,
15561+
"_internalId": 180629,
1556115562
"type": "enum",
1556215563
"enum": [
1556315564
"png",
@@ -15573,7 +15574,7 @@
1557315574
"exhaustiveCompletions": true
1557415575
},
1557515576
"theme": {
15576-
"_internalId": 180142,
15577+
"_internalId": 180636,
1557715578
"type": "anyOf",
1557815579
"anyOf": [
1557915580
{

src/resources/schema/definitions.yml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1406,14 +1406,15 @@
14061406
description: |
14071407
The number of items to include in your feed. Defaults to 20.
14081408
type:
1409-
enum: [full, partial]
1409+
enum: [full, partial, metadata]
14101410
description:
14111411
short: Whether to include full or partial content in the feed.
14121412
long: |
14131413
Whether to include full or partial content in the feed.
14141414
14151415
- `full` (default): Include the complete content of the document in the feed.
14161416
- `partial`: Include only the first paragraph of the document in the feed.
1417+
- `metadata`: Use only the title, description, and other document metadata in the feed.
14171418
title:
14181419
string:
14191420
description:

src/resources/types/schema-types.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -833,10 +833,12 @@ See [https://www.rssboard.org/rss-language-codes](https://www.rssboard.org/rss-l
833833
for a list of valid language codes. */;
834834
type?:
835835
| "full"
836-
| "partial" /* Whether to include full or partial content in the feed.
836+
| "partial"
837+
| "metadata" /* Whether to include full or partial content in the feed.
837838
838839
- `full` (default): Include the complete content of the document in the feed.
839-
- `partial`: Include only the first paragraph of the document in the feed. */;
840+
- `partial`: Include only the first paragraph of the document in the feed.
841+
- `metadata`: Use only the title, description, and other document metadata in the feed. */;
840842
title?:
841843
string; /* The title for this feed. Defaults to the site title provided the Quarto project. */
842844
} /* Enables an RSS feed for the listing. */;

0 commit comments

Comments
 (0)