From bca39a612cad5f340864a4dc62d94cda962985f9 Mon Sep 17 00:00:00 2001 From: retoor Date: Wed, 29 Jan 2025 18:12:22 +0100 Subject: [PATCH] Update. --- pyproject.toml | 3 +- src/snek/app.py | 4 ++ src/snek/static/base.css | 5 ++ src/snek/system/template.py | 99 +++++++++++++++++++++++++++++++++ src/snek/templates/message.html | 10 +++- 5 files changed, 117 insertions(+), 4 deletions(-) create mode 100644 src/snek/system/template.py diff --git a/pyproject.toml b/pyproject.toml index 71e90a7..22ec4eb 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -23,6 +23,7 @@ dependencies = [ "wkhtmltopdf", "mistune", "aiohttp-session", - "cryptography" + "cryptography", + "requests" ] diff --git a/src/snek/app.py b/src/snek/app.py index b1c20c0..c2c3651 100644 --- a/src/snek/app.py +++ b/src/snek/app.py @@ -16,6 +16,7 @@ from snek.system import http from snek.system.cache import Cache from snek.system.markdown import MarkdownExtension from snek.system.middleware import cors_middleware +from snek.system.template import LinkifyExtension, PythonExtension from snek.view.about import AboutHTMLView, AboutMDView from snek.view.docs import DocsHTMLView, DocsMDView from snek.view.index import IndexView @@ -51,6 +52,9 @@ class Application(BaseApplication): session_setup(self, EncryptedCookieStorage(SESSION_KEY)) self._middlewares.append(session_middleware) self.jinja2_env.add_extension(MarkdownExtension) + self.jinja2_env.add_extension(LinkifyExtension) + self.jinja2_env.add_extension(PythonExtension) + self.setup_router() self.cache = Cache(self) self.services = get_services(app=self) diff --git a/src/snek/static/base.css b/src/snek/static/base.css index 4b1e603..0e040e2 100644 --- a/src/snek/static/base.css +++ b/src/snek/static/base.css @@ -209,6 +209,11 @@ message-list { } .message { + max-width: 100%; + word-wrap: break-word; + overflow-wrap: break-word; + hyphens: auto; + .avatar { opacity: 0; } diff --git a/src/snek/system/template.py b/src/snek/system/template.py new file mode 100644 index 0000000..8994528 --- /dev/null +++ b/src/snek/system/template.py @@ -0,0 +1,99 @@ +from types import SimpleNamespace +from bs4 import BeautifulSoup +import re + + + +def set_link_target_blank(text): + soup = BeautifulSoup(text, 'html.parser') + + for element in soup.find_all("a"): + element.attrs['target'] = '_blank' + element.attrs['rel'] = 'noopener noreferrer' + element.attrs['referrerpolicy'] = 'no-referrer' + + return str(soup) + + +def linkify_https(text): + url_pattern = r'(?()]+' + + soup = BeautifulSoup(text, 'html.parser') + + for element in soup.find_all(text=True): + parent = element.parent + if parent.name in ['a', 'script', 'style']: + continue + + new_text = re.sub(url_pattern, r'\g<0>', element) + element.replace_with(BeautifulSoup(new_text, 'html.parser')) + + return set_link_target_blank(str(soup)) + + +from jinja2 import TemplateSyntaxError, nodes +from jinja2.ext import Extension +from jinja2.nodes import Const + + +class LinkifyExtension(Extension): + tags = {"linkify"} + + def __init__(self, environment): + self.app = SimpleNamespace(jinja2_env=environment) + super(LinkifyExtension, self).__init__(environment) + + def parse(self, parser): + line_number = next(parser.stream).lineno + md_file = [Const("")] + body = "" + try: + md_file = [parser.parse_expression()] + except TemplateSyntaxError: + body = parser.parse_statements(["name:endlinkify"], drop_needle=True) + return nodes.CallBlock( + self.call_method("_to_html", md_file), [], [], body + ).set_lineno(line_number) + + def _to_html(self, md_file, caller): + return linkify_https(caller()) + +class PythonExtension(Extension): + tags = {"py3"} + + def parse(self, parser): + line_number = next(parser.stream).lineno + md_file = [Const("")] + body = "" + try: + md_file = [parser.parse_expression()] + except TemplateSyntaxError: + body = parser.parse_statements(["name:endpy3"], drop_needle=True) + return nodes.CallBlock( + self.call_method("_to_html", md_file), [], [], body + ).set_lineno(line_number) + + def _to_html(self, md_file, caller): + + def fn(source): + import subprocess + import subprocess + import pathlib + from pathlib import Path + import os + import sys + import requests + def system(command): + if isinstance(command): + command = command.split(" ") + from io import StringIO + stdout = StringIO() + subprocess.run(command,stderr=stdout,stdout=stdout,text=True) + return stdout.getvalue() + to_write = [] + def render(text): + global to_write + to_write.append(text) + exec(source) + return "".join(to_write) + return str(fn(caller())) \ No newline at end of file diff --git a/src/snek/templates/message.html b/src/snek/templates/message.html index d813397..36faaed 100644 --- a/src/snek/templates/message.html +++ b/src/snek/templates/message.html @@ -1,10 +1,14 @@ + {# -
{{user_nick[0]}}
{{user_nick}}
-#} - {% markdown %}{% autoescape false %}{{ message }}{%raw %} {% endraw%}{%endautoescape%}{% endmarkdown %} +
{{user_nick[0]}}
{{user_nick}}
+#} +{% linkify %} + +{% markdown %}{% autoescape false %}{{ message }}{%raw %} {% endraw%}{%endautoescape%}{% endmarkdown %} +{% endlinkify %} {#
{{created_at}}
#} \ No newline at end of file