3 min read
pyssg.plugins.redirects
Redirects plugin.
Emits a tiny meta refresh HTML page for every old URL -> new URL rule a
site declares, so links to retired paths keep resolving after a migration
(/posts/ -> /, a renamed slug -> its new permalink, /about/ -> an
external CV). Each rule materializes a virtual :class:~pyssg.core.node.Page
with template=None, whose body is the redirect HTML emitted verbatim by the
render plugin (no layout) -- the same "summarizer page" mechanism the
sitemap/rss plugins use.
The rules are literal: the source is the exact old URL (/posts/ ->
posts/index.html) and the target is used as-is, so an absolute path
(/new/) or a full external URL (https://cv.example.com) both work. This
plugin is therefore locale-agnostic by design -- a localized site lists the old
localized URLs explicitly rather than having the engine partition them.
A rule is skipped when its source URL already belongs to a real page (a redirect
must never overwrite live content); the remaining set is materialized
deterministically (sorted by source, body derived purely from the rule and
base_url), so two builds are byte-identical and an incremental rebuild reuses
cached output whenever the rules are unchanged. Rules dropped between builds have
their stale page -- and thus their output -- removed.
The algorithm lives in :class:RedirectsPlugin methods so a site can subclass it
to change the redirect markup (e.g. add a delay or a styled body) or the page-id
scheme without forking the plugin (see AGENTS.md on plugin design).
render_redirect_html(*, target: str, canonical: str) -> str
Build the meta refresh redirect document pointing at target.
target is the value used for the instant <meta http-equiv="refresh">
and the visible fallback link; canonical is the absolute URL advertised to
crawlers via <link rel="canonical">. The page is marked noindex so the
stub itself never competes with the destination in search results. Both URLs
are attribute- and text-escaped, so an ampersand in a query string is safe.
class RedirectsPlugin
Built-in meta refresh redirect generator, one page per rule.
Customise by subclassing: override :meth:render_html for the redirect markup,
:meth:page_id for the node-id scheme, or :meth:canonical_url for how a
site-relative target is made absolute, while reusing the collision check and
emit wiring. Pass the rules through the :func:redirects factory.
RedirectsPlugin.__init__(self, *, rules: Mapping[str, str] | None = None) -> None
RedirectsPlugin.apply(self, builder: Builder) -> None
RedirectsPlugin.page_id(self, source: str) -> str
Stable node id for the redirect page serving source.
RedirectsPlugin.canonical_url(self, target: str, base_url: str) -> str
Absolute URL advertised as canonical for a redirect to target.
An already-absolute target is returned unchanged; a site-relative target
is joined onto base_url so crawlers see a fully-qualified destination.
RedirectsPlugin.render_html(self, source: str, target: str, base_url: str) -> str
Render the redirect document for one source -> target rule.
RedirectsPlugin.build(self, build: Build) -> None
(Re)materialize one redirect page per rule and drop stale ones.
Skips any rule whose source URL or target is empty, or whose source URL is already served by a real page (live content always wins). Iterates the rules sorted by source so the emitted set is order-independent.
build_redirects(build: Build, rules: Mapping[str, str] | None = None) -> None
Materialize the redirect pages. Thin wrapper around :meth:RedirectsPlugin.build.
redirects(rules: Mapping[str, str] | None = None) -> RedirectsPlugin
Factory used in pyssg.config.py.
rules maps each old URL to its replacement; see :class:RedirectsPlugin.