From a253c324f33516876e70610ce403a3f123c02d0f Mon Sep 17 00:00:00 2001 From: =?utf8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Sun, 6 May 2018 14:33:47 +0200 Subject: [PATCH] plugins: new plugin m.alias. --- doc/plugins.rst | 14 ++-- doc/plugins/links.rst | 47 ++++++++++++- doc/plugins/math-and-code.rst | 2 +- doc/plugins/metadata.rst | 2 +- pelican-plugins/m/alias.py | 69 +++++++++++++++++++ .../m/test/alias/articles/article.rst | 5 ++ .../m/test/alias/blog/old-article/index.html | 2 + .../m/test/alias/even-older-page.html | 1 + .../m/test/alias/old-page/index.html | 1 + pelican-plugins/m/test/alias/page.rst | 6 ++ pelican-plugins/m/test/test_alias.py | 39 +++++++++++ site/pelicanconf.py | 4 +- 12 files changed, 179 insertions(+), 13 deletions(-) create mode 100644 pelican-plugins/m/alias.py create mode 100644 pelican-plugins/m/test/alias/articles/article.rst create mode 100644 pelican-plugins/m/test/alias/blog/old-article/index.html create mode 100644 pelican-plugins/m/test/alias/even-older-page.html create mode 100644 pelican-plugins/m/test/alias/old-page/index.html create mode 100644 pelican-plugins/m/test/alias/page.rst create mode 100644 pelican-plugins/m/test/test_alias.py diff --git a/doc/plugins.rst b/doc/plugins.rst index 5386f144..b216fad3 100644 --- a/doc/plugins.rst +++ b/doc/plugins.rst @@ -49,7 +49,8 @@ and restart Pelican. Download the plugins below or :gh:`m.dox `, :gh:`m.gl `, :gh:`m.abbr `, - :gh:`m.filesize ` + :gh:`m.filesize `, + :gh:`m.alias ` - :gh:`m.metadata ` Click on the headings below to get to know more. Note that particular plugins @@ -85,12 +86,13 @@ rendering and syntax highlighting, so they are provided as separate packages that you can but don't have to use. With these, math and code snippets can be entered directly in your :abbr:`reST ` sources. -`Links » <{filename}/plugins/links.rst>`_ -========================================= +`Links and other » <{filename}/plugins/links.rst>`_ +=================================================== -The :py:`m.gh`, :py:`m.dox`, :py:`m.gl`, :py:`m.abbr` and :py:`m.fiilesize` -plugins make it easy for you to link to GitHub projects, issues or PRs, to -Doxygen documentation and do more useful things. +The :py:`m.gh`, :py:`m.dox`, :py:`m.gl`, :py:`m.abbr`, :py:`m.fiilesize` and +:py:`m.alias` plugins make it easy for you to link to GitHub projects, issues +or PRs, to Doxygen documentation, query file sizes and provide URL aliases to +preserve link compatibility. `Metadata » <{filename}/plugins/metadata.rst>`_ =============================================== diff --git a/doc/plugins/links.rst b/doc/plugins/links.rst index 329229ce..a9fb8899 100644 --- a/doc/plugins/links.rst +++ b/doc/plugins/links.rst @@ -22,15 +22,15 @@ DEALINGS IN THE SOFTWARE. .. -Links -##### +Links and other +############### :breadcrumb: {filename}/plugins.rst Pelican plugins :footer: .. note-dim:: :class: m-text-center - `« Math and code <{filename}/plugins/math-and-code.rst>`_ | `Pelican plugins <{filename}/plugins.rst>`_ + `« Math and code <{filename}/plugins/math-and-code.rst>`_ | `Pelican plugins <{filename}/plugins.rst>`_ | `Metadata » <{filename}/plugins/metadata.rst>`_ .. role:: py(code) :language: py @@ -262,3 +262,44 @@ first before calculating the size. :filesize:`{filename}/../css/m-dark.compiled.css` but only :filesize-gz:`{filename}/../css/m-dark.compiled.css` when the server sends it compressed. + +`Aliases`_ +========== + +Site content almost never stays on the same place for extended periods of time +and preserving old links for backwards compatibility is a vital thing for user +friendliness. This plugin allows you to create a redirect alias URLs for your +pages and articles. + +Download the `m/alias.py <{filename}/plugins.rst>`_ file, put it +including the ``m/`` directory into one of your :py:`PLUGIN_PATHS` and add +:py:`m.alias` package to your :py:`PLUGINS` in ``pelicanconf.py``. This plugin +assumes presence of `m.htmlsanity <{filename}/plugins/htmlsanity.rst>`_. + +.. code:: python + + PLUGINS += ['m.htmlsanity', 'm.alias'] + +.. note-success:: + + This plugin is loosely inspired by :gh:`Nitron/pelican-alias`, © 2013 + Christopher Williams, licensed under + :gh:`MIT `. + +Use the :rst:`:alias:` field to specify one or more locations that should +redirect to your article / page. Each line is treated as one alias, the +locations have to begin with ``/`` and are relative to the Pelican output +directory, each of them contains just a :html:`` +that points to a fully-qualified URL of the article or page. + +If the alias ends with ``/``, the redirector file is saved into ``index.html`` +in given directory. + +.. code:: rst + + My Article + ########## + + :alias: + /2018/05/06/old-version-of-the-article/ + /even-older-version-of-the-article.html diff --git a/doc/plugins/math-and-code.rst b/doc/plugins/math-and-code.rst index 36f7da02..a3210ea6 100644 --- a/doc/plugins/math-and-code.rst +++ b/doc/plugins/math-and-code.rst @@ -30,7 +30,7 @@ Math and code .. note-dim:: :class: m-text-center - `« Images <{filename}/plugins/images.rst>`_ | `Pelican plugins <{filename}/plugins.rst>`_ | `Links » <{filename}/plugins/links.rst>`_ + `« Images <{filename}/plugins/images.rst>`_ | `Pelican plugins <{filename}/plugins.rst>`_ | `Links and other » <{filename}/plugins/links.rst>`_ .. role:: css(code) :language: css diff --git a/doc/plugins/metadata.rst b/doc/plugins/metadata.rst index 5c0878ad..1a65e2ee 100644 --- a/doc/plugins/metadata.rst +++ b/doc/plugins/metadata.rst @@ -32,7 +32,7 @@ Metadata .. note-dim:: :class: m-text-center - `« Links <{filename}/plugins/links.rst>`_ | `Pelican plugins <{filename}/plugins.rst>`_ + `« Links and other <{filename}/plugins/links.rst>`_ | `Pelican plugins <{filename}/plugins.rst>`_ .. role:: html(code) :language: html diff --git a/pelican-plugins/m/alias.py b/pelican-plugins/m/alias.py new file mode 100644 index 00000000..c4e96fca --- /dev/null +++ b/pelican-plugins/m/alias.py @@ -0,0 +1,69 @@ +# +# This file is part of m.css. +# +# Copyright © 2017, 2018 Vladimír Vondruš +# +# Loosely based on https://github.com/Nitron/pelican-alias, +# copyright © 2013 Christopher Williams +# +# Permission is hereby granted, free of charge, to any person obtaining a +# copy of this software and associated documentation files (the "Software"), +# to deal in the Software without restriction, including without limitation +# the rights to use, copy, modify, merge, publish, distribute, sublicense, +# and/or sell copies of the Software, and to permit persons to whom the +# Software is furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included +# in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +# DEALINGS IN THE SOFTWARE. +# + +import os +import logging +from pelican import signals + +from m.htmlsanity import format_siteurl + +logger = logging.getLogger(__name__) + +class AliasGenerator: + def __init__(self, context, settings, path, theme, output_path, *args): + self.output_path = output_path + self.context = context + + def generate_output(self, writer): + for page in self.context['pages'] + self.context['articles']: + aliases = page.metadata.get('alias', '').strip() + if not aliases: continue + for alias in aliases.split('\n'): + alias = alias.strip() + + # Currently only supporting paths starting with / + if not alias.startswith('/'): assert False + path = os.path.join(self.output_path, alias[1:]) + + # If path ends with /, write it into index.html + directory, filename = os.path.split(path) + if not filename: filename = 'index.html' + + alias_file = os.path.join(directory, filename) + alias_target = format_siteurl(page.url) + logger.info('m.alias: creating alias {} -> {}'.format(alias_file[len(self.output_path):], alias_target)) + + # Write the redirect file + os.makedirs(directory, exist_ok=True) + with open(alias_file, 'w') as f: + f.write("""\n""".format(alias_target)) + +def get_generators(generators): return AliasGenerator + +def register(): + # TODO: why `lambda generators: AliasGenerator` doesn't work? + signals.get_generators.connect(get_generators) diff --git a/pelican-plugins/m/test/alias/articles/article.rst b/pelican-plugins/m/test/alias/articles/article.rst new file mode 100644 index 00000000..bec8fd56 --- /dev/null +++ b/pelican-plugins/m/test/alias/articles/article.rst @@ -0,0 +1,5 @@ +An Article +########## + +:date: 2018-05-06 +:alias: /blog/old-article/ diff --git a/pelican-plugins/m/test/alias/blog/old-article/index.html b/pelican-plugins/m/test/alias/blog/old-article/index.html new file mode 100644 index 00000000..356c5b34 --- /dev/null +++ b/pelican-plugins/m/test/alias/blog/old-article/index.html @@ -0,0 +1,2 @@ + + diff --git a/pelican-plugins/m/test/alias/even-older-page.html b/pelican-plugins/m/test/alias/even-older-page.html new file mode 100644 index 00000000..529cb893 --- /dev/null +++ b/pelican-plugins/m/test/alias/even-older-page.html @@ -0,0 +1 @@ + diff --git a/pelican-plugins/m/test/alias/old-page/index.html b/pelican-plugins/m/test/alias/old-page/index.html new file mode 100644 index 00000000..529cb893 --- /dev/null +++ b/pelican-plugins/m/test/alias/old-page/index.html @@ -0,0 +1 @@ + diff --git a/pelican-plugins/m/test/alias/page.rst b/pelican-plugins/m/test/alias/page.rst new file mode 100644 index 00000000..48483a30 --- /dev/null +++ b/pelican-plugins/m/test/alias/page.rst @@ -0,0 +1,6 @@ +A page +###### + +:alias: + /old-page/ + /even-older-page.html diff --git a/pelican-plugins/m/test/test_alias.py b/pelican-plugins/m/test/test_alias.py new file mode 100644 index 00000000..9f18135d --- /dev/null +++ b/pelican-plugins/m/test/test_alias.py @@ -0,0 +1,39 @@ +# +# This file is part of m.css. +# +# Copyright © 2017, 2018 Vladimír Vondruš +# +# Permission is hereby granted, free of charge, to any person obtaining a +# copy of this software and associated documentation files (the "Software"), +# to deal in the Software without restriction, including without limitation +# the rights to use, copy, modify, merge, publish, distribute, sublicense, +# and/or sell copies of the Software, and to permit persons to whom the +# Software is furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included +# in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +# DEALINGS IN THE SOFTWARE. +# + +from m.test import PluginTestCase + +class Alias(PluginTestCase): + def __init__(self, *args, **kwargs): + super().__init__(__file__, '', *args, **kwargs) + + def test(self): + self.run_pelican({ + 'PLUGINS': ['m.htmlsanity', 'm.alias'], + 'SITEURL': 'http://my.site' + }) + + self.assertEqual(*self.actual_expected_contents('old-page/index.html')) + self.assertEqual(*self.actual_expected_contents('even-older-page.html')) + self.assertEqual(*self.actual_expected_contents('blog/old-article/index.html')) diff --git a/site/pelicanconf.py b/site/pelicanconf.py index 18755760..226f3614 100644 --- a/site/pelicanconf.py +++ b/site/pelicanconf.py @@ -87,7 +87,7 @@ M_LINKS_NAVBAR2 = [('Pelican plugins', 'plugins/', 'plugins', [ ('Components', 'plugins/components/', 'plugins/components'), ('Images', 'plugins/images/', 'plugins/images'), ('Math and code', 'plugins/math-and-code/', 'plugins/math-and-code'), - ('Links', 'plugins/links/', 'plugins/links'), + ('Links and other', 'plugins/links/', 'plugins/links'), ('Metadata', 'plugins/metadata/', 'plugins/metadata')]), ('Doxygen theme', 'doxygen/', 'doxygen', []), ('GitHub', 'https://github.com/mosra/m.css', '', [])] @@ -118,7 +118,7 @@ M_LINKS_FOOTER4 = [('Pelican plugins', 'plugins/'), ('Components', 'plugins/components/'), ('Images', 'plugins/images/'), ('Math and code', 'plugins/math-and-code/'), - ('Links', 'plugins/links/'), + ('Links and other', 'plugins/links/'), ('Metadata', 'plugins/metadata/')] M_FINE_PRINT = """ -- 2.30.2