mews.page/pelican-mews/README.md

130 lines
3.8 KiB
Markdown
Raw Permalink Normal View History

2026-10-11 08:09:18 +03:00
# 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 `<html>`. 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 bundled `pelican/plugins/mews/dtd/mews.dtd` is a minimal placeholder.
Replace it with the real Mews Profile DTD when it is available; the plugin
picks up the change without any code edit.
## 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`. |
### 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
<!DOCTYPE html PUBLIC "-//WAPFORUM//DTD XHTML Mobile 1.2//EN"
"http://www.openmobilealliance.org/tech/DTD/xhtml-mobile12.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="{{ DEFAULT_LANG }}" lang="{{ DEFAULT_LANG }}">
<head>
<title>{{ page.title }}</title>
{% include "mews/head.html" %}
</head>
```
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
```