61 lines
1.6 KiB
Python
61 lines
1.6 KiB
Python
"""Pick the slide-XML schema errors PowerPoint refuses the file over.
|
|
|
|
A denylist over lxml's messages, so an unrecognised error class is a miss rather
|
|
than a false alarm.
|
|
"""
|
|
|
|
|
|
from __future__ import annotations
|
|
|
|
import re
|
|
|
|
SLIDE_PART_RE = re.compile(
|
|
r"ppt/(slides|slideLayouts|slideMasters|notesSlides|notesMasters|handoutMasters)"
|
|
r"/[^/]+\.xml"
|
|
)
|
|
|
|
FATAL_SLIDE_ERRORS: tuple[tuple[re.Pattern[str], str], ...] = (
|
|
(
|
|
re.compile(r"\}tableStyleId': This element is not expected"),
|
|
"two <a:tableStyleId> in one <a:tblPr> (the schema allows one)",
|
|
),
|
|
(
|
|
re.compile(r"\}srgbClr', attribute 'val'"),
|
|
"a colour that is not six hex digits",
|
|
),
|
|
(
|
|
re.compile(r"\}txBody': Missing child element"),
|
|
"a <p:txBody> with no children",
|
|
),
|
|
(
|
|
re.compile(r"\}miter', attribute 'lim'"),
|
|
'a line join with lim="NaN"',
|
|
),
|
|
(
|
|
re.compile(r"\}uLnTx': This element is not expected"),
|
|
"<a:uLnTx> in a position the schema forbids",
|
|
),
|
|
(
|
|
re.compile(r"\}overrideClrMapping': This element is not expected"),
|
|
"<p:overrideClrMapping> in a position the schema forbids",
|
|
),
|
|
(
|
|
re.compile(r"\}nvGrpSpPr': Missing child element"),
|
|
"a <p:nvGrpSpPr> with no children",
|
|
),
|
|
)
|
|
|
|
|
|
def is_schema_verdict(error: str) -> bool:
|
|
return error.startswith("Element ")
|
|
|
|
|
|
def fatal_slide_errors(errors: set[str]) -> list[str]:
|
|
out = []
|
|
for error in sorted(errors):
|
|
for pattern, meaning in FATAL_SLIDE_ERRORS:
|
|
if pattern.search(error):
|
|
out.append(f"{meaning}: {error}")
|
|
break
|
|
return out
|