Files
cms-SiteForge/app/preview_rewrite.py
T

45 lines
1.8 KiB
Python
Raw Normal View History

"""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)