# pelican-mews Make Pelican output pages in Mews Profile format: a small-web subset of XHTML Mobile Profile 1.2 that any browser or WAP 2.0 phone can read. The plugin reads the allowed elements and attributes from the bundled Mews DTD, so the subset is data, not code. Every file Pelican writes that ends in `.xhtml` is parsed as XML, brought inside the subset, and re-serialized as well-formed UTF-8 XML with the XHTML namespace on ``. The plugin also copies the Mews stylesheet into the output tree and gives themes a `MEWS_CSS` global plus the `mews/head.html` partial. The subset comes from `pelican/plugins/mews/dtd/mews.dtd`, which is a copy of the Mews Profile 0.1 DTD. Only element and attribute names are read from it, so the plugin lists none of them in code: change the DTD and the allowlist changes with it. ## Install ```shell pip install pelican-mews ``` Pelican loads the plugin from the `pelican.plugins.mews` module, so the `pelican` and `pelican.plugins` namespace packages installed by other plugins coexist with this one. ## Settings Pages and articles must be written as `.xhtml`, and Markdown must render as XHTML, so the plugin has valid XML to work on: ```python PLUGINS = ["pelican.plugins.mews"] MARKDOWN = { "output_format": "xhtml", } PAGE_URL = "{slug}.xhtml" PAGE_SAVE_AS = "{slug}.xhtml" ARTICLE_URL = "{slug}.xhtml" ARTICLE_SAVE_AS = "{slug}.xhtml" ``` If your `PLUGINS` list is already set, add `"pelican.plugins.mews"` to it. Three optional settings: | Setting | Default | Meaning | | --- | --- | --- | | `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 To keep a normal blog output untouched and build the Mews tree in parallel, point `MEWS_OUTPUT_PATH` at a folder of its own. Pelican still writes the `.xhtml` pages where `*_SAVE_AS` says, but the plugin moves the finished page into `MEWS_OUTPUT_PATH`, keeping the subpath it had under `OUTPUT_PATH`, and copies the stylesheet there too. The main output ends up without any Mews files: ```python # Articles keep their normal HTML output. ARTICLE_URL = "{slug}.html" ARTICLE_SAVE_AS = "{slug}.html" # Only pages become Mews pages, in a tree of their own. PAGE_URL = "{slug}.xhtml" PAGE_SAVE_AS = "{slug}.xhtml" MEWS_OUTPUT_PATH = "mews-output" ``` The folder works like `OUTPUT_PATH`: a relative path is resolved from the working directory, so `mews-output` sits beside `output`. ## Themes The plugin ships partials only, never a full base template. Include the head partial from your page template: ```jinja {{ page.title }} {% include "mews/head.html" %} ``` The partial renders the conformance marker, the viewport, and the stylesheet link with `{{ MEWS_CSS }}` (for example `css/mews-0.1.css`). Your theme keeps responsibility for the doctype, the namespace, and the rest of the page. ## Serving .xhtml Serve Mews pages as `application/xhtml+xml` so browsers parse them as XML. A page the plugin has written is well-formed, so XML mode is safe. nginx: ```nginx location ~ \.xhtml$ { types { } default_type application/xhtml+xml; } ``` Apache, in `.htaccess`: ```apache AddType application/xhtml+xml .xhtml ``` Python's built-in server already maps `.xhtml` to `application/xhtml+xml`: ```shell python -m http.server ``` ## Testing ```shell uv sync --group test uv run pytest ```