From c5d04240b1747663c9ceea463d7b1b0c52f68d5e Mon Sep 17 00:00:00 2001 From: Jake Howard Date: Sun, 16 Jul 2023 14:30:08 +0100 Subject: [PATCH] Add styles to feeds Copied from https://darekkay.com/blog/rss-styling/ --- scripts/copy-npm-contrib.sh | 2 ++ website/blog/tests.py | 3 ++- website/common/tests/test_pages.py | 3 ++- website/common/views.py | 33 ++++++++++++++++++++++++++---- 4 files changed, 35 insertions(+), 6 deletions(-) diff --git a/scripts/copy-npm-contrib.sh b/scripts/copy-npm-contrib.sh index fcf0a5d..392fe5e 100755 --- a/scripts/copy-npm-contrib.sh +++ b/scripts/copy-npm-contrib.sh @@ -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' {} \; diff --git a/website/blog/tests.py b/website/blog/tests.py index e49fac5..74b103b 100644 --- a/website/blog/tests.py +++ b/website/blog/tests.py @@ -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") diff --git a/website/common/tests/test_pages.py b/website/common/tests/test_pages.py index dafa683..cda22cb 100644 --- a/website/common/tests/test_pages.py +++ b/website/common/tests/test_pages.py @@ -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") diff --git a/website/common/views.py b/website/common/views.py index dbabebf..31bae65 100644 --- a/website/common/views.py +++ b/website/common/views.py @@ -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''.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