diff --git a/mews/quickstart.py b/mews/quickstart.py index 0b1f488..504ade4 100644 --- a/mews/quickstart.py +++ b/mews/quickstart.py @@ -41,16 +41,13 @@ DEFAULT_LANG = "en" THEME = "theme" # The plugin reads the allowed elements and attributes from the Mews DTD and -# brings every page inside that subset. +# brings every page inside that subset. It only touches files ending .xhtml, +# so everything has to be written out under that suffix. PLUGINS = ["pelican.plugins.mews"] -# This whole site is Mews, so its pages are plain .html: a server sends those -# as text/html, which section 7.1 asks for so a small markup error still shows -# as a page, and index.html is the directory index everywhere. The plugin -# defaults to .xhtml instead, for sites that are only partly Mews. -MEWS_SUFFIX = ".html" -ARTICLE_URL = ARTICLE_SAVE_AS = "{{slug}}.html" -PAGE_URL = PAGE_SAVE_AS = "{{slug}}.html" +ARTICLE_URL = ARTICLE_SAVE_AS = "{{slug}}.xhtml" +PAGE_URL = PAGE_SAVE_AS = "{{slug}}.xhtml" +INDEX_SAVE_AS = "index.xhtml" # Markdown has to produce XML for the plugin to parse. Tables and definition # lists are both in the Mews subset but need their extensions turned on. @@ -62,11 +59,7 @@ MARKDOWN = {{ }}, }} -# Every page written under MEWS_SUFFIX goes through the plugin, and Pelican -# falls back to its own HTML templates for these when the theme has none. They -# have nothing to show on a site like this, so they stay off; give them -# templates in theme/templates/ if you want them. -DIRECT_TEMPLATES = ["index"] +# Mews pages carry no author styling, so there is nothing for these to show. AUTHOR_SAVE_AS = CATEGORY_SAVE_AS = TAG_SAVE_AS = "" AUTHORS_SAVE_AS = CATEGORIES_SAVE_AS = TAGS_SAVE_AS = ARCHIVES_SAVE_AS = "" # Pelican writes several feeds by default and they are all broken until @@ -122,7 +115,7 @@ ARTICLE = """\ {% block content %}

{{ article.title }}

{{ article.content }} -

All posts

+

All posts

{% endblock %} """ @@ -132,7 +125,7 @@ PAGE = """\ {% block content %}

{{ page.title }}

{{ page.content }} -

All posts

+

All posts

{% endblock %} """ @@ -164,8 +157,7 @@ A Mews site. The pages follow [Mews Profile 0.1](https://mews.page/spec/0.1). uv run pelican content ``` -The finished pages land in `output/`, as plain `.html` that any web server -serves correctly with no configuration. To work on it with a reload on save: +The finished pages land in `output/`. To work on it with a reload on save: ```shell uv run pelican --autoreload --listen content @@ -173,7 +165,12 @@ uv run pelican --autoreload --listen content ## Publish it -Copy `output/` to any web server. Nothing to configure. +Copy `output/` to any web server. Two things are worth setting: + +- Serve `.xhtml` files as `text/html`. Section 7.1 of the spec asks for that, + so a browser still shows a page carrying a small markup error. +- Make `index.xhtml` the directory index, since the plugin only processes + files under that suffix. In Caddy: `file_server {{ index index.xhtml }}`. ## Subscribe to it diff --git a/pelican-mews/README.md b/pelican-mews/README.md index 0088b0e..5c11a88 100644 --- a/pelican-mews/README.md +++ b/pelican-mews/README.md @@ -52,7 +52,6 @@ Three optional settings: | `MEWS_STRICT` | `False` | Fail the build on content outside the subset instead of stripping it. Removals are always logged either way. | | `MEWS_CSS_DIR` | `"css"` | Directory below the output root where `mews-0.1.css` is copied. Themes see the resulting path as the `MEWS_CSS` global. | | `MEWS_OUTPUT_PATH` | unset | Put the finished pages in this folder instead of `OUTPUT_PATH`. | -| `MEWS_SUFFIX` | `".xhtml"` | Which written files are Mews pages. Set it to `".html"` on a site that is Mews throughout, and save your pages under that suffix too: servers send `.xhtml` as `application/xhtml+xml`, which makes a browser parse the page as XML and fail outright on a small markup error, while section 7.1 asks for `text/html` so the page still shows. `index.html` is also the directory index everywhere, which `index.xhtml` is not. Note that `.html` puts every page Pelican writes through the plugin, including the index, tag and archive pages it falls back to when the theme has no template for them, so give those a Mews template or switch them off with `DIRECT_TEMPLATES` and the matching `*_SAVE_AS` settings. | ### Rendering beside an existing blog diff --git a/pelican-mews/pelican/plugins/mews/mews.py b/pelican-mews/pelican/plugins/mews/mews.py index 983be2c..babe147 100644 --- a/pelican-mews/pelican/plugins/mews/mews.py +++ b/pelican-mews/pelican/plugins/mews/mews.py @@ -47,13 +47,7 @@ LOGGER = logging.getLogger(__name__) CSS_NAME = "mews-0.1.css" DEFAULT_CSS_DIR = "css" -# Which files Pelican writes are Mews pages. The default keeps the plugin off -# everything else, so it can run on a site that also produces ordinary HTML. -# A site that is Mews throughout wants ".html" instead: servers send .xhtml as -# application/xhtml+xml, which makes a browser parse as XML and fail hard on a -# small markup error, and section 7.1 asks for text/html precisely to avoid -# that. Set MEWS_SUFFIX to choose. -DEFAULT_SUFFIX = ".xhtml" +XHTML_SUFFIX = ".xhtml" ALLOWLIST = parse_allowlist( files(__package__).joinpath("dtd", "mews.dtd").read_text(encoding="utf-8") @@ -73,12 +67,6 @@ def _on_initialized(pelican) -> None: overrides.append(templates) -def _suffix() -> str: - """Return the file extension a Mews page is written under, with its dot.""" - suffix = str(_settings.get("MEWS_SUFFIX", DEFAULT_SUFFIX)).strip() - return suffix if suffix.startswith(".") else f".{suffix}" - - def _on_generator_init(generator) -> None: css_dir = generator.settings.get("MEWS_CSS_DIR", DEFAULT_CSS_DIR) generator.env.globals["MEWS_CSS"] = f"{css_dir}/{CSS_NAME}" @@ -86,7 +74,7 @@ def _on_generator_init(generator) -> None: def _on_content_written(path, **_) -> None: file = Path(path) - if file.suffix != _suffix(): + if file.suffix != XHTML_SUFFIX: return try: tree, doctype = parse_page(file.read_bytes()) diff --git a/pelican-mews/tests/test_mews.py b/pelican-mews/tests/test_mews.py index 3b22e83..7267aa0 100644 --- a/pelican-mews/tests/test_mews.py +++ b/pelican-mews/tests/test_mews.py @@ -28,44 +28,6 @@ def test_written_page_matches_expected(tmp_path, case): assert normalize(page) == normalize(expected) -def test_a_site_can_choose_its_own_suffix(tmp_path): - """A site that is Mews throughout writes .html, so servers send text/html.""" - output = build_case( - "basic", - tmp_path, - MEWS_SUFFIX=".html", - PAGE_SAVE_AS="{slug}.html", - PAGE_URL="{slug}.html", - # With .html the plugin sees every page Pelican writes, including the - # index, tags and archives it falls back to when the theme has no - # template for them. Those fallbacks are HTML, not XML, so a site - # using .html has to give every direct template a Mews template or - # switch the lot off, as here. - DIRECT_TEMPLATES=[], - ) - page = (output / "page.html").read_bytes() - assert normalize(page) == normalize( - (FIXTURES / "basic" / "expected.xhtml").read_bytes() - ) - - -def test_the_default_suffix_leaves_other_html_alone(tmp_path): - """Left at its default the plugin must not touch a plain HTML page.""" - output = build_case( - "strip", - tmp_path, - PAGE_SAVE_AS="{slug}.html", - PAGE_URL="{slug}.html", - INDEX_SAVE_AS="", - ) - # The strip fixture carries a , a class and a comment, all three of - # which the plugin removes. Untouched, every one of them survives. - written = (output / "page.html").read_bytes() - assert b"' in index + index = (site / "output" / "index.xhtml").read_text() + assert '
  • ' in index