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",
"mistune",
"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.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)

View File

@ -209,6 +209,11 @@ message-list {
}
.message {
max-width: 100%;
word-wrap: break-word;
overflow-wrap: break-word;
hyphens: auto;
.avatar {
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>
{{highlight_styles}}
</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>
#}