Add styles to feeds

Copied from https://darekkay.com/blog/rss-styling/
This commit is contained in:
Jake Howard 2023-07-16 14:30:08 +01:00
parent 530503d769
commit c5d04240b1
Signed by: jake
GPG key ID: 57AFB45680EDD477
4 changed files with 35 additions and 6 deletions

View file

@ -23,5 +23,7 @@ mkcontrib fira-code/files node_modules/@fontsource/fira-code/files/fira-code-lat
mkcontrib htmx node_modules/htmx.org/dist/{htmx.min.js,ext}
mkcontrib glightbox node_modules/glightbox/dist/css/glightbox.min.css
curl -sf -L https://raw.githubusercontent.com/genmon/aboutfeeds/main/tools/pretty-feed-v3.xsl -o $CONTRIB_DIR/pretty-feed-v3.xsl
# HACK: Make sure Google lighthouse can tell we're using `font-display: swap`
find $CONTRIB_DIR/fira-code -type f -exec sed -i 's/var(--fontsource-display, swap)/swap/g' {} \;

View file

@ -85,4 +85,5 @@ class BlogPostListPageTestCase(TestCase):
self.page.url + self.page.reverse_subpage("feed")
)
self.assertEqual(response.status_code, 200)
self.assertEqual(response["Content-Type"], "application/rss+xml; charset=utf-8")
self.assertEqual(response["Content-Type"], "application/xml")
self.assertContains(response, "xml-stylesheet")

View file

@ -64,4 +64,5 @@ class ListingPageTestCase(TestCase):
self.page.url + self.page.reverse_subpage("feed")
)
self.assertEqual(response.status_code, 200)
self.assertEqual(response["Content-Type"], "application/rss+xml; charset=utf-8")
self.assertEqual(response["Content-Type"], "application/xml")
self.assertContains(response, "xml-stylesheet")

View file

@ -4,6 +4,7 @@ from typing import Any, Optional
from django.contrib.syndication.views import Feed
from django.http.request import HttpRequest
from django.http.response import HttpResponse
from django.templatetags.static import static
from django.urls import reverse
from django.utils.decorators import method_decorator
from django.views.decorators.cache import cache_control, cache_page
@ -12,6 +13,7 @@ from django.views.generic import TemplateView
from wagtail.models import Page
from wagtail.query import PageQuerySet
from website.common.utils import get_site_title
from website.contrib.singleton_page.utils import SingletonPageCache
from website.home.models import HomePage
from website.search.models import SearchPage
@ -56,15 +58,35 @@ class KeybaseView(TemplateView):
class AllPagesFeed(Feed):
link = "/feed/"
title = "All pages feed"
link = "/"
def __init__(self) -> None:
self.style_tag = f'<?xml-stylesheet href="{static("contrib/pretty-feed-v3.xsl")}" type="text/xsl"?>'.encode()
super().__init__()
@method_decorator(cache_page(60 * 60))
def __call__(
self, request: HttpRequest, *args: list, **kwargs: dict
) -> HttpResponse:
self.request = request
return super().__call__(request, *args, **kwargs)
response = super().__call__(request, *args, **kwargs)
# Override Content-Type to allow styles
response.headers["content-type"] = "application/xml"
# Inject styles
opening_xml = response.content.find(b"?>") + 2
response.content = (
response.content[:opening_xml]
+ b"\n"
+ self.style_tag
+ response.content[opening_xml:]
)
return response
def title(self) -> str:
return f"All Pages Feed :: {get_site_title()}"
def items(self) -> PageQuerySet:
return (
@ -109,8 +131,11 @@ class ContentPageFeed(AllPagesFeed):
def __init__(self, posts: PageQuerySet, link: str, title: str):
self.posts = posts
self.link = link
self.title = title
self._title = title
super().__init__()
def title(self) -> str:
return self._title
def items(self) -> PageQuerySet:
return self.posts