This commit is contained in:
retoor 2025-01-29 18:12:22 +01:00
parent f69586ccf7
commit bca39a612c
5 changed files with 117 additions and 4 deletions

View File

@ -23,6 +23,7 @@ dependencies = [
"wkhtmltopdf", "wkhtmltopdf",
"mistune", "mistune",
"aiohttp-session", "aiohttp-session",
"cryptography" "cryptography",
"requests"
] ]

View File

@ -16,6 +16,7 @@ from snek.system import http
from snek.system.cache import Cache from snek.system.cache import Cache
from snek.system.markdown import MarkdownExtension from snek.system.markdown import MarkdownExtension
from snek.system.middleware import cors_middleware from snek.system.middleware import cors_middleware
from snek.system.template import LinkifyExtension, PythonExtension
from snek.view.about import AboutHTMLView, AboutMDView from snek.view.about import AboutHTMLView, AboutMDView
from snek.view.docs import DocsHTMLView, DocsMDView from snek.view.docs import DocsHTMLView, DocsMDView
from snek.view.index import IndexView from snek.view.index import IndexView
@ -51,6 +52,9 @@ class Application(BaseApplication):
session_setup(self, EncryptedCookieStorage(SESSION_KEY)) session_setup(self, EncryptedCookieStorage(SESSION_KEY))
self._middlewares.append(session_middleware) self._middlewares.append(session_middleware)
self.jinja2_env.add_extension(MarkdownExtension) self.jinja2_env.add_extension(MarkdownExtension)
self.jinja2_env.add_extension(LinkifyExtension)
self.jinja2_env.add_extension(PythonExtension)
self.setup_router() self.setup_router()
self.cache = Cache(self) self.cache = Cache(self)
self.services = get_services(app=self) self.services = get_services(app=self)

View File

@ -209,6 +209,11 @@ message-list {
} }
.message { .message {
max-width: 100%;
word-wrap: break-word;
overflow-wrap: break-word;
hyphens: auto;
.avatar { .avatar {
opacity: 0; opacity: 0;
} }

View File

@ -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'(?<!["\'])\bhttps://[^\s<>()]+'
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'<a href="\g<0>">\g<0></a>', 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()))

View File

@ -1,10 +1,14 @@
<style> <style>
{{highlight_styles}} {{highlight_styles}}
</style> </style>
{# {#
<div data-uid="{{uid}}" data-color="{{color}}" data-channel_uid="{{channel_uid}}" data-user_nick="{{user_nick}}" data-created_at="{{created_at}}" data-user_uid="{{user_uid}}" data-message="{{message}}" class="message"><div class="avatar" style="background-color: {{color}}; color: black;">{{user_nick[0]}}</div><div class="message-content"><div class="author" style="color: {{color}};">{{user_nick}}</div><div class="text"> <div style="max-width:100%;" data-uid="{{uid}}" data-color="{{color}}" data-channel_uid="{{channel_uid}}" data-user_nick="{{user_nick}}" data-created_at="{{created_at}}" data-user_uid="{{user_uid}}" data-message="{{message}}" class="message"><div class="avatar" style="background-color: {{color}}; color: black;">{{user_nick[0]}}</div><div class="message-content"><div class="author" style="color: {{color}};">{{user_nick}}</div><div class="text">
#} #}
{% markdown %}{% autoescape false %}{{ message }}{%raw %} {% endraw%}{%endautoescape%}{% endmarkdown %} {% linkify %}
{% markdown %}{% autoescape false %}{{ message }}{%raw %} {% endraw%}{%endautoescape%}{% endmarkdown %}
{% endlinkify %}
{# {#
</div><div class="time">{{created_at}}</div></div></div> </div><div class="time">{{created_at}}</div></div></div>
#} #}