Normalize Birch page shell during finalization
Browse files- research/app_artifacts.py +20 -1
research/app_artifacts.py
CHANGED
|
@@ -23,6 +23,12 @@ MARKER_STYLE_RE = re.compile(
|
|
| 23 |
rf"<style\b[^>]*>\s*{re.escape(MARKER)}\s*</style>",
|
| 24 |
re.I | re.S,
|
| 25 |
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 26 |
|
| 27 |
|
| 28 |
def finalize_bucket_html(
|
|
@@ -62,7 +68,7 @@ def finalize_bucket_html(
|
|
| 62 |
return _artifact_urls(username, job.id)
|
| 63 |
|
| 64 |
css = _birch_css_path(home).read_text()
|
| 65 |
-
finalized = _inject_birch_css(html, css)
|
| 66 |
_validate_html(finalized)
|
| 67 |
api.batch_bucket_files(
|
| 68 |
bucket_id,
|
|
@@ -110,6 +116,17 @@ def _inject_birch_css(html: str, css: str) -> str:
|
|
| 110 |
return html.replace(MARKER, css.strip())
|
| 111 |
|
| 112 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 113 |
def _download_first(
|
| 114 |
api: Any,
|
| 115 |
bucket_id: str,
|
|
@@ -155,6 +172,8 @@ def _validate_html(html: str) -> None:
|
|
| 155 |
raise ValueError("HTML artifact has no doctype")
|
| 156 |
if not STYLE_RE.search(html):
|
| 157 |
raise ValueError("HTML artifact has no embedded Birch stylesheet")
|
|
|
|
|
|
|
| 158 |
if "</html>" not in html.lower():
|
| 159 |
raise ValueError("HTML artifact is incomplete")
|
| 160 |
|
|
|
|
| 23 |
rf"<style\b[^>]*>\s*{re.escape(MARKER)}\s*</style>",
|
| 24 |
re.I | re.S,
|
| 25 |
)
|
| 26 |
+
PAGE_RE = re.compile(
|
| 27 |
+
r'<main\b[^>]*\bclass=["\'][^"\']*\bpage\b[^"\']*["\']',
|
| 28 |
+
re.I,
|
| 29 |
+
)
|
| 30 |
+
MAIN_CLASS_RE = re.compile(r'(<main\b[^>]*\bclass=["\'])([^"\']*)', re.I)
|
| 31 |
+
MAIN_RE = re.compile(r"<main\b", re.I)
|
| 32 |
|
| 33 |
|
| 34 |
def finalize_bucket_html(
|
|
|
|
| 68 |
return _artifact_urls(username, job.id)
|
| 69 |
|
| 70 |
css = _birch_css_path(home).read_text()
|
| 71 |
+
finalized = _ensure_page_shell(_inject_birch_css(html, css))
|
| 72 |
_validate_html(finalized)
|
| 73 |
api.batch_bucket_files(
|
| 74 |
bucket_id,
|
|
|
|
| 116 |
return html.replace(MARKER, css.strip())
|
| 117 |
|
| 118 |
|
| 119 |
+
def _ensure_page_shell(html: str) -> str:
|
| 120 |
+
"""Add Birch's required `.page` class to the first main element."""
|
| 121 |
+
if PAGE_RE.search(html):
|
| 122 |
+
return html
|
| 123 |
+
if MAIN_CLASS_RE.search(html):
|
| 124 |
+
return MAIN_CLASS_RE.sub(r"\1page \2", html, count=1)
|
| 125 |
+
if MAIN_RE.search(html):
|
| 126 |
+
return MAIN_RE.sub('<main class="page"', html, count=1)
|
| 127 |
+
return html
|
| 128 |
+
|
| 129 |
+
|
| 130 |
def _download_first(
|
| 131 |
api: Any,
|
| 132 |
bucket_id: str,
|
|
|
|
| 172 |
raise ValueError("HTML artifact has no doctype")
|
| 173 |
if not STYLE_RE.search(html):
|
| 174 |
raise ValueError("HTML artifact has no embedded Birch stylesheet")
|
| 175 |
+
if not PAGE_RE.search(html):
|
| 176 |
+
raise ValueError("HTML artifact has no Birch page shell")
|
| 177 |
if "</html>" not in html.lower():
|
| 178 |
raise ValueError("HTML artifact is incomplete")
|
| 179 |
|