validator/ holds mewslint (lint, css, fetch, DTD/CSS data); directory/ holds the mews.page service (app, db, check, pages, cli) and depends on validator/; quickstart/ holds mews-quickstart and md2mews.py for third parties who want to create Mews content without cloning the repo; spec/ consolidates doc/ and dtd/ with the canonical mews-0.1.css; site/ becomes a Pelican project with the forward-facing pages as Markdown, the check form kept as a raw HTML snippet. Root pyproject.toml is now a virtual uv workspace over validator, directory and quickstart, with cross-cutting tests that span more than one of them staying at the repo root. Makefile and flake.nix updated to match.
67 lines
2.2 KiB
Python
67 lines
2.2 KiB
Python
"""The page emitter, against md2mews.py's.
|
|
|
|
directory.pages repeats md2mews.page() because md2mews.py is a standalone
|
|
script with its own dependencies. This is what keeps the two in step.
|
|
"""
|
|
|
|
import importlib.util
|
|
from pathlib import Path
|
|
import sys
|
|
|
|
import pytest
|
|
|
|
from directory import pages
|
|
|
|
ROOT = Path(__file__).resolve().parent.parent
|
|
|
|
|
|
def load_md2mews():
|
|
"""Import md2mews.py, which is a script rather than part of a package."""
|
|
spec = importlib.util.spec_from_file_location(
|
|
"md2mews", ROOT / "quickstart" / "md2mews.py"
|
|
)
|
|
module = importlib.util.module_from_spec(spec)
|
|
sys.modules["md2mews"] = module
|
|
spec.loader.exec_module(module)
|
|
return module
|
|
|
|
|
|
CASES = [
|
|
("Plain", [" <p>x</p>"], "en", None, None, None),
|
|
("With a variant", [" <p>x</p>"], "en", None, "mews-cool", None),
|
|
("Right to left", [" <p>x</p>"], "he", "rtl", None, None),
|
|
("Described", [" <p>x</p>"], "en", None, "mews-warm", "A page."),
|
|
("An ampersand & a <tag>", [" <p>x</p>"], "en", None, None, None),
|
|
]
|
|
|
|
|
|
@pytest.mark.parametrize("case", CASES)
|
|
def test_the_two_emitters_agree(case):
|
|
"""Same prologue, head order, body attributes and escaping of & and <.
|
|
|
|
The two differ on quote characters in text, which md2mews.py escapes
|
|
because its one escape helper also fills attribute values. Both are
|
|
well-formed; mews.pages leaves them alone so prose reads as prose.
|
|
"""
|
|
md2mews = pytest.importorskip("mistune") and load_md2mews()
|
|
title, body, language, direction, variant, description = case
|
|
assert pages.page(title, body, language, direction, variant, description) == (
|
|
md2mews.page(title, body, language, direction, variant, description)
|
|
)
|
|
|
|
|
|
def test_a_message_page_conforms():
|
|
from mews.lint import validate_bytes
|
|
|
|
text = pages.message("Hello", ["One.", "Two."], [("/", "Home")])
|
|
assert validate_bytes(text.encode()).conforms
|
|
|
|
|
|
def test_quotes_in_text_are_left_alone():
|
|
text = pages.site_page('A "quoted" title', [" <p>x</p>"])
|
|
assert '<title>A "quoted" title</title>' in text
|
|
|
|
|
|
def test_an_apostrophe_is_not_escaped():
|
|
text = pages.message("Hello", ["It isn't escaped."], [("/", "Home")])
|
|
assert "isn't escaped" in text
|