Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 32 additions & 0 deletions docs/configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -550,6 +550,38 @@ Default: `False`.

----

### :material-brush-variant: `stylesheet`: define a XSL stylesheet { #stylesheet }

Use a XSL stylesheet to customize how the RSS feed looks like. `auto` is a special value to use the stylesheet shipped with the plugin.

```yaml
plugins:
- rss:
stylesheet: auto
```

If you're willing to work on your own stylesheet, set the URL or relative path:

```yaml
plugins:
- rss:
stylesheet: https://docs.example.org/rss_stylesheet.xsl
```

Note that it's recommended to host the stylesheet on the same website / domain to make CORS happy.

If you prefer to disable the stylesheet, you set it to `""`:

```yaml
plugins:
- rss:
stylesheet: ""
```

Default: `auto`.

----

### :material-track-light: `url_parameters`: additional URL parameters { #url_parameters }

This option allows you to add parameters to the URLs of the RSS feed items. It works as a dictionary of keys/values that is passed to [Python *urllib.parse.urlencode*](https://docs.python.org/3/library/urllib.parse.html#urllib.parse.urlencode).
Expand Down
1 change: 1 addition & 0 deletions mkdocs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,7 @@ plugins:
match_path: ".*"
pretty_print: true
rss_feed_enabled: true
stylesheet: auto
url_parameters:
utm_source: "documentation"
utm_medium: "RSS"
Expand Down
1 change: 1 addition & 0 deletions mkdocs_rss_plugin/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ class RssPluginConfig(Config):
match_path = config_options.Type(str, default=".*")
pretty_print = config_options.Type(bool, default=False)
rss_feed_enabled = config_options.Type(bool, default=True)
stylesheet = config_options.Type(str, default="auto")
url_parameters = config_options.Optional(config_options.Type(dict))
use_git = config_options.Type(bool, default=True)
use_material_blog = config_options.Type(bool, default=True)
Expand Down
1 change: 1 addition & 0 deletions mkdocs_rss_plugin/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -90,5 +90,6 @@ class RssFeedBase:
pubDate: str | None = None
repo_url: str | None = None
rss_url: str | None = None
stylesheet: str | None = None
title: str | None = None
ttl: int | None = None
24 changes: 24 additions & 0 deletions mkdocs_rss_plugin/plugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
from email.utils import format_datetime, formatdate
from pathlib import Path
from re import compile as re_compile
from shutil import copyfile
from typing import Literal

# 3rd party
Expand Down Expand Up @@ -88,7 +89,7 @@
self.feed_created: RssFeedBase = RssFeedBase()
self.feed_updated: RssFeedBase = RssFeedBase()

def on_config(self, config: MkDocsConfig) -> MkDocsConfig:

Check failure on line 92 in mkdocs_rss_plugin/plugin.py

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Refactor this function to reduce its Cognitive Complexity from 20 to the 15 allowed.

See more on https://sonarcloud.io/project/issues?id=Guts_mkdocs-rss-plugin&issues=AZ1z52KVkpOC1dcbOPmq&open=AZ1z52KVkpOC1dcbOPmq&pullRequest=432
"""The config event is the first event called on build and
is run immediately after the user configuration is loaded and validated.
Any alterations to the config should be made here.
Expand Down Expand Up @@ -175,6 +176,23 @@
if self.config.image:
base_feed.logo_url = self.config.image

# feed stylesheet (XSL)
print(f"Config stylesheet: {self.config.stylesheet}")
if self.config.stylesheet:
if self.config.stylesheet == "auto":
base_feed.stylesheet = "rss.xsl"
logger.debug(
f"Shipped stylesheet will be referenced in RSS feeds: {self.config.stylesheet}"
)
else:

base_feed.stylesheet = self.config.stylesheet
logger.debug(
f"Stylesheet will be referenced in RSS feeds: {self.config.stylesheet}"
)
else:
logger.debug("No stylesheet will be referenced in RSS feeds.")

# pattern to match pages included in output
self.match_path_pattern = re_compile(self.config.match_path)

Expand Down Expand Up @@ -378,6 +396,12 @@
self.config.feeds_filenames.json_updated
)

# stylesheet for RSS feed
if self.config.stylesheet == "auto":
xsl_source = self.tpl_folder.joinpath("default.xsl")
xsl_dest = Path(config.site_dir).joinpath("rss.xsl")
copyfile(xsl_source, xsl_dest)

# created items
self.feed_created.entries.extend(
self.util.filter_pages(
Expand Down
188 changes: 188 additions & 0 deletions mkdocs_rss_plugin/templates/default.xsl
Original file line number Diff line number Diff line change
@@ -0,0 +1,188 @@
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:atom="http://www.w3.org/2005/Atom"
xmlns:dc="http://purl.org/dc/elements/1.1/">

<xsl:output method="html" encoding="UTF-8" indent="yes"/>

<xsl:template match="/">
<html>
<head>
<meta charset="UTF-8"/>
<title>
<xsl:value-of select="rss/channel/title"/>
</title>
<style>
body {
font-family: system-ui, -apple-system, BlinkMacSystemFont, sans-serif;
max-width: 900px;
margin: 40px auto;
padding: 0 20px;
background: #f9fafb;
color: #111827;
}

header {
border-bottom: 2px solid #e5e7eb;
padding-bottom: 20px;
margin-bottom: 30px;
}

header img {
vertical-align: middle;
margin-right: 15px;
}
header .meta {
margin-top: 15px;
font-size: 0.9em;
color: #6b7280;
}

h1 {
margin: 0;
}

.item {
background: white;
padding: 20px;
margin-bottom: 25px;
border-radius: 10px;
box-shadow: 0 4px 12px rgba(0,0,0,0.05);
}

.item h2 {
margin-top: 0;
}

.meta {
font-size: 0.9em;
color: #6b7280;
margin-bottom: 10px;
}

.categories span {
background: #eef2ff;
color: #3730a3;
padding: 3px 8px;
margin-right: 5px;
border-radius: 6px;
font-size: 0.75em;
}

.item img {
max-width: 100%;
margin: 15px 0;
border-radius: 8px;
}

a {
color: #2563eb;
text-decoration: none;
}

a:hover {
text-decoration: underline;
}
</style>
</head>

<body>

<header>
<xsl:if test="rss/channel/image/url">
<img>
<xsl:attribute name="src">
<xsl:value-of select="rss/channel/image/url"/>
</xsl:attribute>
<xsl:attribute name="width">64</xsl:attribute>
</img>
</xsl:if>

<h1>
<xsl:value-of select="rss/channel/title"/>
</h1>

<p>
<xsl:value-of select="rss/channel/description"/>
</p>

<p>
<a>
<xsl:attribute name="href">
<xsl:value-of select="rss/channel/link"/>
</xsl:attribute>
Visit website
</a>
</p>
<div class="meta">

<xsl:if test="author">
By <xsl:value-of select="author"/>
</xsl:if>

<xsl:if test="pubDate">
— <strong>Published:</strong>
<xsl:value-of select="pubDate"/>
</xsl:if>

<xsl:if test="updated">
— <strong>Updated:</strong>
<xsl:value-of select="updated"/>
</xsl:if>

</div>
</header>

<xsl:for-each select="rss/channel/item">

<div class="item">

<h2>
<a>
<xsl:attribute name="href">
<xsl:value-of select="link"/>
</xsl:attribute>
<xsl:value-of select="title"/>
</a>
</h2>

<div class="meta">
<xsl:if test="author">
Par <xsl:value-of select="author"/>
</xsl:if>
<xsl:if test="pubDate">
— <xsl:value-of select="pubDate"/>
</xsl:if>
</div>

<!-- Image si enclosure image/* -->
<xsl:if test="enclosure[starts-with(@type,'image/')]">
<img>
<xsl:attribute name="src">
<xsl:value-of select="enclosure/@url"/>
</xsl:attribute>
</img>
</xsl:if>

<p>
<xsl:value-of select="description"/>
</p>

<div class="categories">
<xsl:for-each select="category">
<span>
<xsl:value-of select="."/>
</span>
</xsl:for-each>
</div>

</div>

</xsl:for-each>

</body>
</html>
</xsl:template>

</xsl:stylesheet>
1 change: 1 addition & 0 deletions mkdocs_rss_plugin/templates/rss.xml.jinja2
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
{% if feed.stylesheet is not none %}<?xml-stylesheet type="text/xsl" href="{{ feed.stylesheet }}"?>{% endif -%}
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
<channel>
{# Mandatory elements #}
Expand Down
12 changes: 12 additions & 0 deletions tests/fixtures/mkdocs_stylesheet_disabled.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
site_name: Test RSS Plugin - Disable stylesheet
# site_description: Test RSS Plugin
site_url: https://guts.github.io/mkdocs-rss-plugin

use_directory_urls: true

plugins:
- rss:
stylesheet: ""

theme:
name: mkdocs
2 changes: 2 additions & 0 deletions tests/test_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@ def test_plugin_config_defaults(self):
"rss_updated": "feed_rss_updated.xml",
},
"pretty_print": False,
"stylesheet": "auto",
"rss_feed_enabled": True,
"url_parameters": None,
"use_git": True,
Expand Down Expand Up @@ -134,6 +135,7 @@ def test_plugin_config_image(self):
"rss_updated": "feed_rss_updated.xml",
},
"pretty_print": False,
"stylesheet": "auto",
"rss_feed_enabled": True,
"url_parameters": None,
"use_git": True,
Expand Down
Loading