8cea7dee20
- SiteForge Enterprise V8.10.0-dev.1 upstream source (210 tests) - Fix: v8_workflows._mapped_input now reads both 类型/分类 columns so WXR imports keep post/product types instead of collapsing to page - Docs: trade-pro theme port spec (R3) and implementation plan Co-Authored-By: Claude Code <noreply@anthropic.com>
45 lines
1.8 KiB
Python
45 lines
1.8 KiB
Python
"""Rewrite root-relative links only in the HTTP preview response.
|
|
|
|
The published ZIP / immutable build files are never modified. Source element
|
|
markup is preserved so that e.g. canonical links and SEO headers are not
|
|
rewritten or reformatted by an HTML serializer.
|
|
"""
|
|
import re
|
|
from html.parser import HTMLParser
|
|
|
|
_ATTR = re.compile(r'''(?P<name>\b(?:href|src|action|poster))(?P<eq>\s*=\s*)(?P<q>["'])(?P<value>.*?)(?P=q)''', re.I | re.S)
|
|
|
|
class _PreviewHTMLParser(HTMLParser):
|
|
def __init__(self, prefix):
|
|
super().__init__(convert_charrefs=False)
|
|
self.prefix=prefix
|
|
self.out=[]
|
|
|
|
def _start(self):
|
|
raw=self.get_starttag_text()
|
|
def replace(match):
|
|
url=match.group('value')
|
|
if url.startswith('/') and not url.startswith('//') and not url.startswith(self.prefix):
|
|
url=self.prefix + url.lstrip('/')
|
|
return match.group('name')+match.group('eq')+match.group('q')+url+match.group('q')
|
|
self.out.append(_ATTR.sub(replace,raw))
|
|
|
|
def handle_starttag(self,tag,attrs): self._start()
|
|
def handle_startendtag(self,tag,attrs): self._start()
|
|
def handle_endtag(self,tag): self.out.append(f'</{tag}>')
|
|
def handle_data(self,data): self.out.append(data)
|
|
def handle_comment(self,data): self.out.append(f'<!--{data}-->')
|
|
def handle_decl(self,decl): self.out.append(f'<!{decl}>')
|
|
def handle_entityref(self,name): self.out.append(f'&{name};')
|
|
def handle_charref(self,name): self.out.append(f'&#{name};')
|
|
def handle_pi(self,data): self.out.append(f'<?{data}>')
|
|
def unknown_decl(self,data): self.out.append(f'<![{data}]>')
|
|
|
|
|
|
def rewrite_preview_html(document: str, site_id: str, build_id: str) -> str:
|
|
prefix=f'/preview/{site_id}/{build_id}/'
|
|
parser=_PreviewHTMLParser(prefix)
|
|
parser.feed(document)
|
|
parser.close()
|
|
return ''.join(parser.out)
|