diff --git a/docs/_static/theme-basic.zip b/docs/_static/theme-basic.zip deleted file mode 100644 index d1e4754a..00000000 Binary files a/docs/_static/theme-basic.zip and /dev/null differ diff --git a/docs/themes.rst b/docs/themes.rst index fa4c9d37..c17d0fbd 100644 --- a/docs/themes.rst +++ b/docs/themes.rst @@ -589,38 +589,12 @@ using the ``{% extends %}`` directive as in the following example: Example ------- -With this system, it is possible to create a theme with just two files. +With this system, it is possible to create a theme with just one file. -base.html -""""""""" +main.css +"""""""" -The first file is the ``templates/base.html`` template: - -.. code-block:: html+jinja - - {% extends "!simple/base.html" %} - - {% block head %} - {{ super() }} - - {% endblock %} - -1. On the first line, we extend the ``base.html`` template from the ``simple`` - theme, so we don't have to rewrite the entire file. -2. On the third line, we open the ``head`` block which has already been defined - in the ``simple`` theme. -3. On the fourth line, the function ``super()`` keeps the content previously - inserted in the ``head`` block. -4. On the fifth line, we append a stylesheet to the page. -5. On the last line, we close the ``head`` block. - -This file will be extended by all the other templates, so the stylesheet will -be linked from all pages. - -style.css -""""""""" - -The second file is the ``static/css/style.css`` CSS stylesheet: +The file is ``static/css/main.css`` (the default ``CSS_FILE``): .. code-block:: css @@ -663,10 +637,32 @@ The second file is the ``static/css/style.css`` CSS stylesheet: margin-top : 1em ; } -Download -"""""""" +Custom templates +"""""""""""""""" -You can download this example theme :download:`here <_static/theme-basic.zip>`. +If you want to customise the templates as well, you can extend them. For +example, to add a custom footer, create a ``templates/base.html``: + +.. code-block:: html+jinja + + {% extends "!simple/base.html" %} + + {% block footer %} +

Custom footer

+ {{ super() }} + {% endblock %} + +1. On the first line, we extend the ``base.html`` template from the ``simple`` + theme, so we don't have to rewrite the entire file. +2. On the third line, we open the ``footer`` block which has already been + defined in the ``simple`` theme. +3. On the fourth line, we insert the extra footer content. +4. On the fifth line, the function ``super()`` keeps the content previously + inserted in the ``head`` block. +5. On the last line, we close the ``footer`` block. + +This file will be extended by all the other templates, so the custom footer +will appear on all pages. .. Links diff --git a/pelican/settings.py b/pelican/settings.py index dbe903f1..29761f70 100644 --- a/pelican/settings.py +++ b/pelican/settings.py @@ -592,6 +592,17 @@ def configure_settings(settings: Settings) -> Settings: else: raise Exception("Could not find the theme {}".format(settings["THEME"])) + # Clear CSS_FILE if the file doesn't exist in the theme + css_file = settings.get("CSS_FILE") + if css_file: + theme = settings["THEME"] + static_paths = settings.get("THEME_STATIC_PATHS", ["static"]) + if not any( + os.path.isfile(os.path.join(theme, sp, "css", css_file)) + for sp in static_paths + ): + settings["CSS_FILE"] = "" + # standardize strings to lowercase strings for key in ["DEFAULT_LANG"]: if key in settings: diff --git a/pelican/tests/test_theme.py b/pelican/tests/test_theme.py index aa996081..c4bd6f14 100644 --- a/pelican/tests/test_theme.py +++ b/pelican/tests/test_theme.py @@ -201,6 +201,97 @@ class TestTemplateInheritance(LoggedTestCase): tag_content = f.read() self.assertIn('title="Foo Tag Atom Feed"', tag_content) + def test_simple_theme_no_css_link(self): + """The simple theme has no static/css/ directory, so the CSS_FILE + link should not be rendered.""" + + settings = read_settings( + path=None, + override={ + "THEME": "simple", + "PATH": CONTENT_DIR, + "OUTPUT_PATH": self.temp_output, + "CACHE_PATH": self.temp_cache, + "SITEURL": "http://example.com", + }, + ) + + pelican = Pelican(settings=settings) + mute(True)(pelican.run)() + + with open(os.path.join(self.temp_output, "test-md-file.html")) as f: + content = f.read() + + self.assertNotIn("/theme/css/main.css", content) + + def test_child_theme_with_css_file(self): + """A child theme that provides static/css/main.css should have the + CSS_FILE link rendered.""" + + # Add a CSS file to the child theme + css_dir = os.path.join(self.temp_theme, "static", "css") + os.makedirs(css_dir) + with open(os.path.join(css_dir, "main.css"), "w") as f: + f.write("body { margin: 0; }") + + settings = read_settings( + path=None, + override={ + "THEME": self.temp_theme, + "PATH": CONTENT_DIR, + "OUTPUT_PATH": self.temp_output, + "CACHE_PATH": self.temp_cache, + "SITEURL": "http://example.com", + }, + ) + + pelican = Pelican(settings=settings) + mute(True)(pelican.run)() + + with open(os.path.join(self.temp_output, "test-md-file.html")) as f: + content = f.read() + + self.assertIn( + 'href="http://example.com/theme/css/main.css"', + content, + ) + + def test_css_only_theme(self): + """A theme with only a static/css/main.css file (no templates) + should work by falling back to the simple theme's templates.""" + + css_only_theme = mkdtemp(prefix="pelican_test_css_only_theme.") + css_dir = os.path.join(css_only_theme, "static", "css") + os.makedirs(css_dir) + with open(os.path.join(css_dir, "main.css"), "w") as f: + f.write("body { margin: 0; }") + + try: + settings = read_settings( + path=None, + override={ + "THEME": css_only_theme, + "PATH": CONTENT_DIR, + "OUTPUT_PATH": self.temp_output, + "CACHE_PATH": self.temp_cache, + "SITEURL": "http://example.com", + }, + ) + + pelican = Pelican(settings=settings) + mute(True)(pelican.run)() + + with open(os.path.join(self.temp_output, "test-md-file.html")) as f: + content = f.read() + + self.assertIn( + 'href="http://example.com/theme/css/main.css"', + content, + ) + self.assertIn("Proudly powered by", content) + finally: + rmtree(css_only_theme) + if __name__ == "__main__": unittest.main() diff --git a/pelican/themes/simple/templates/base.html b/pelican/themes/simple/templates/base.html index 57d2bafd..d86e38f8 100644 --- a/pelican/themes/simple/templates/base.html +++ b/pelican/themes/simple/templates/base.html @@ -9,6 +9,9 @@ {% if SITESUBTITLE %} {% endif %} + {% if CSS_FILE %} + + {% endif %} {% if STYLESHEET_URL %} {% endif %}