aboutsummaryrefslogtreecommitdiff
path: root/cgit/filters/html-transform.py
diff options
context:
space:
mode:
authorAkshay Nair <phenax5@gmail.com>2026-07-04 10:53:44 +0530
committerAkshay Nair <phenax5@gmail.com>2026-07-04 10:53:44 +0530
commit6b505a48a23f77867dd9dc75a542ede6ce4ae955 (patch)
treee080c3c88f8c449681f45abaccf906230b2ead09 /cgit/filters/html-transform.py
parent1f4c276914a7e5b03a31345d7bf5966e8aff9081 (diff)
downloadbacchus-remote-6b505a48a23f77867dd9dc75a542ede6ce4ae955.tar.gz
bacchus-remote-6b505a48a23f77867dd9dc75a542ede6ce4ae955.zip
Fix html transformation for about + syntax hl changes
Diffstat (limited to 'cgit/filters/html-transform.py')
-rwxr-xr-xcgit/filters/html-transform.py83
1 files changed, 83 insertions, 0 deletions
diff --git a/cgit/filters/html-transform.py b/cgit/filters/html-transform.py
new file mode 100755
index 0000000..9fc7aec
--- /dev/null
+++ b/cgit/filters/html-transform.py
@@ -0,0 +1,83 @@
+#!/usr/bin/env python3
+# Rewrite image urls in about section
+
+import sys
+from html.parser import HTMLParser
+import html
+from urllib.parse import urljoin, urlparse
+import re
+
+def is_absolute_url(url):
+ if not url: return False
+ parsed = urlparse(url)
+ return bool(parsed.netloc or parsed.scheme)
+
+def is_relative_path(url):
+ if not url: return False
+ return not url.startswith("/") and not is_absolute_url(url)
+
+def linkify(text, make_link):
+ url_pattern = r'(?<!\S)(https?://\S+?)([.,!?;:]?(?=\s|$))'
+ def replace(m):
+ url, trail = m.group(1), m.group(2)
+ return make_link(url) + trail
+ return re.sub(url_pattern, replace, text)
+
+class LinkRewriter(HTMLParser):
+ def __init__(self):
+ super().__init__(convert_charrefs=False)
+ self.output = []
+
+ def get_html(self):
+ return "".join(self.output)
+
+ def _build_tag(self, tag, attrs, self_closing = False):
+ new_tag = tag
+ attr_map = {}
+ for name, value in attrs:
+ if name in ("href", "src") and is_relative_path(value) and not value.startswith('#'):
+ if tag == 'a':
+ value = "../" + urljoin("tree/", value)
+ else:
+ value = "../" + urljoin("plain/", value)
+ attr_map[name] = value
+ # Open in new tab
+ if tag == "a" and name == "href" and is_absolute_url(value):
+ if not 'target' in attr_map: attr_map['target'] = '_blank _parent'
+ if not 'rel' in attr_map: attr_map['rel'] = 'noopener'
+
+ attr_str = "".join(
+ f' {name}="{html.escape(value, quote=True)}"' if value is not None else f" {name}"
+ for name, value in attr_map.items()
+ )
+ return f"<{new_tag}{attr_str}{' /' if self_closing else ''}>"
+
+ def handle_starttag(self, tag, attrs):
+ self.output.append(self._build_tag(tag, attrs))
+
+ def handle_startendtag(self, tag, attrs):
+ self.output.append(self._build_tag(tag, attrs, self_closing=True))
+
+ def handle_endtag(self, tag):
+ self.output.append(f"</{tag}>")
+
+ def handle_data(self, data):
+ data_with_links = linkify(data,
+ lambda url: self._build_tag("a", [('href', url)]) + html.escape(url) + "</a>")
+ self.output.append(data_with_links)
+
+ def handle_entityref(self, name):
+ self.output.append(f"&{name};")
+
+ def handle_charref(self, name):
+ self.output.append(f"&#{name};")
+
+ def handle_comment(self, data):
+ self.output.append(f"<!--{data}-->")
+
+html_in = sys.stdin.read()
+
+parser = LinkRewriter()
+parser.feed(html_in)
+
+print(parser.get_html())