Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

💡 RFC: Feed templates #1657

Closed
3 tasks
innermatrix opened this issue Oct 26, 2021 · 7 comments
Closed
3 tasks

💡 RFC: Feed templates #1657

innermatrix opened this issue Oct 26, 2021 · 7 comments

Comments

@innermatrix
Copy link

innermatrix commented Oct 26, 2021

Background & Motivation

Feeds currently generated by Astro are hard-coded in src/build/rss.ts and can't be customized. This is a problem because

  • It's difficult to output a feed in a different format (Atom vs RSS)
  • It's difficult to output multiple feed formats
  • While the author can insert additional data into each <item> via customData, they cannot insert any additional data into a <channel>.
  • The custom data inserted into <item> is specified as a raw string, and therefore not subject to any of the syntactic conveniences of Astro/JSX templating

Proposed Solution

Possible solutions

Instead of using the rss callback, allow an Astro template to fully specify the format of the feed. Additionally, allow a template to specify which feed (or feeds) it wants to output.

See below for specifics.

Alternatives considered

  • Instead of having one template specify both the HTML content and the feed content, could use a separate template to generate the feed. I think that would lead to code duplication between the content template and the feed template, but it would make it easier to push feed generation into a plugin.

Risks, downsides, and/or tradeoffs

Open Questions

No idea how much demand there will be for feed customization, different feed formats, and multiple feeds.

Detailed Design

I propose the following changes:

  1. Extend Astro templating to be able to output XML in addition to HTML, thereby allowing an Astro template to output the entire feed
  2. Add top-level template export named getFeeds, which (when implemented by a template) will return the formats the template expects to output and their output filenames — for example, {'rss2': 'feed.xml', 'atom1': 'atom.xml'}
  3. Support getFeeds for static routes as well as dynamic routes, thereby allowing src/pages/index.astro to output a top-level feed.
  4. When a template exports getFeeds, it will be called once to generate the content and then once again for each feed type. When called to generate a feed, it will be passed an additional parameter (in Astro.props?), specifying which feed it is supposed to generate. It can then dispatch on this parameter to either generate HTML content or feed content.
  5. Implement an Astro.Feed XML component that outputs the feed in the same format that today's rss() callback uses, to give an easy transition path to templates currently using rss(); then deprecate rss().

For example:

---
export function getFeeds() {
  return [{
    rss2: 'feed.xml'
  }]
}

export interface Props {
  feed?: string;
}

const { feed } = Astro.props as Props;
---

{
feed ? <Feed />
: <Content />
}

For convenience, would be a good idea to allow getFeeds to return a single string S, and treat that as if it had returned [{S: 'feed.xml'}].

Help make it happen!

  • I am willing to submit a PR to implement this change.
  • I am willing to submit a PR to implement this change, but would need some guidance.
  • I am not willing to submit a PR to implement this change.
@matthewp
Copy link
Contributor

matthewp commented Nov 1, 2021

Thank you for being so thorough on your idea! From reading this, this part sticks out to me:

Extend Astro templating to be able to output XML in addition to HTML, thereby allowing an Astro template to output the entire feed

Astro parses as HTML, not XML, and it would probably be non-trivial to change that (correct me if you disagree @natemoo-re). Given that, we could not guarantee that the output was correct HTML if we went with this proposal. Would it be enough to put the burden on the developer that their template did produce correct XML?

@jonathantneal
Copy link
Contributor

jonathantneal commented Nov 1, 2021

There are few issues, which may or may not be difficult:

  • Either append or support <?xml version="1.0" encoding="UTF-8" ?> without translating it into <!--?xml version="1.0" encoding="UTF-8" ?-->.
  • Detect the xml from either the opening <?xml version="1.0" encoding="UTF-8" ?> or the file feed.xml.astro so that <html>, <head>, and <body> are not appended to the feed.
---
const site = {}
---
<?xml version="1.0" encoding="UTF-8" ?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
	<channel>
		<title>{site.name} - Latest Posts</title>
		<description>{site.description}</description>
		<link>{site.url}</link>
		<atom:link href={site.feed_url} rel="self" type="application/rss+xml" />
		{site.posts.map(post => (
			<item>
				<title>{post.title}</title>
				<description>{post.content}</description>
				<pubDate>{post.date}</pubDate>
				<link>{site.url}{post.url}</link>
				<guid>{site.url}{post.url}</guid>
			</item>
		))}
	</channel>
</rss>

@innermatrix
Copy link
Author

innermatrix commented Nov 1, 2021

@jonathantneal It's not necessary (in my proposal) to detect XML automatically; the compiler knows when it's invoking the template to generate page HTML and when it's invoking it to generate a feed, and it can assume XML output in the latter case.

@jonathantneal
Copy link
Contributor

@innermatrix, if we could detect the xml from just the file extension like feed.xml.astro (in order to not generate the <html>, <head>, <body>), would that provide you the functionality you are requesting?

@innermatrix
Copy link
Author

@jonathantneal

Today we have one astro file that generates an html file and a feed XML file (via the rss callback). I like this because it couples "generate HTML that is a list of pages" and "generate RSS that is a list of pages". I was attempting to preserve this feature, which is why I am pitching an API that maintains the "one astro → one HTML + one RSS" mapping. And if you assume "one astro → one HTML + one RSS" then inference from file extension makes no sense — you have to have the ability to generate HTML or XML from the same astro file.

However, if you are willing to give up that coupling, and want to instead consider "one astro → one HTML or one RSS (but not both)", then sure, extension-based inference meets my goals.

I hope that clarifies why I was initially pushing back on going down the road of file extension inference.

@jonathantneal
Copy link
Contributor

@innermatrix, the desire for coupling makes sense. Thank you for clarifying it, definitely.

I think I was resistant to the idea of using the same data to create a page with HTML markup, but then a feed with JS objects.

@FredKSchott
Copy link
Member

Hey everyone! Our current RFC process is beginning to break down at this size, with over 50 open RFCs currently in the "discussing" stage. A growing community is a great problem to have, but our ability to give you RFC feedback has suffered as a result. In an effort to improve our RFC process, we are making some changes to better organize things.

From now on, all RFCs will live in a standalone repo: https://github.com/withastro/rfcs

This allows us to do three things: 1) Use threaded discussions for high-level ideas and improvements, without necessarily requiring an implementation for every idea. 2) Improve the quality of our RFC template and the speed/quality of all feedback. 3) Support inline comments and explicit approvals on RFCs, via a new Pull Request review process.

We hope that this new process leads to better RFC weekly calls and faster feedback on your RFCs from maintainers. More detail can be found in the new RFC repo README.


We can't automatically convert this issue to an RFC in the new repo because new RFC template is more detailed that this one. But, you can still continue this discussion in the new repo by creating a new Discussion in the RFC repo and copy-and-pasting this post (and any relevant follow-up comments) into it. Discussions are available for high-level ideas and suggestions without the requirement of a full implementation proposal.

Then, when you are ready to propose (or re-propose) an implementation for feedback and approval, you can create a new RFC using the new RFC template. More detail about how to do this can be found in the new RFC repo README.

Thanks for your patience as we attempt to improve things for both authors and reviewers. If you have any questions, don't hesitate to reach out on Discord. https://astro.build/chat

💡 RFC Tracker [No Longer Used] automation moved this from Discussing to Abandoned (used old RFC template) Nov 24, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
No open projects
💡 RFC Tracker [No Longer Used]
Abandoned (used old RFC template)
Development

No branches or pull requests

4 participants