2025.12.22 18:39:25 (cachyos.cmoser.eu)

This commit is contained in:
2025-12-22 18:39:25 +01:00
parent 84a4c22f66
commit ba8afc5c5b
4 changed files with 144 additions and 106 deletions

BIN
static/icons/favicon.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

@@ -17,29 +17,58 @@ from .text_formatters import (
render_youtube_video, render_youtube_video,
) )
from .simple_formatters import SIMPLE_FORMATTERS from .simple_formatters import SIMPLE_FORMATTERS # noqa: F401
# a list of tuples containig an tuple args and a dict of kwargs # a list of tuples containig an tuple args and a dict of kwargs
#a list of tuples containing an tuple of args and a dict of kwargs # a list of tuples containing an tuple of args and a dict of kwargs
FORMATTERS=[ FORMATTERS=[
(('url',render_url),{'strip':True,'swallow_trailing_newline':True,'same_tag_closes':True}), (
(('wiki-url',render_wiki_url),{'strip':True,'swallow_trailing_newline':True,'same_tag_closes':True}), ('url', render_url),
(('wiki',render_wiki_link),{'strip':True,'swallow_tailin_newline':True,'standalone':True}), {
(('codeblock',render_codeblock),{'strip':True,'swallow_trailing_newline':False,'same_tag_closes':False,"render_embedded":False}), 'strip': True,
(('ol',render_ordered_list),{}), 'swallow_trailing_newline': True,
(('ul',render_unordered_list),{}), 'same_tag_closes': True
(('li',render_list_item),{}), }
(('p',render_paragraph),{'same_tag_closes':False}), ),
(('image',render_image),{'same_tag_closes':True}), (
(('img',render_image),{'same_tag_closes':True}), ('wiki-url', render_wiki_url),
(('wiki-image',render_wiki_image),{'standalone':True}), {
(('wimg',render_wiki_image),{'standalone':True}), 'strip': True,
(('table',render_table),{}), 'swallow_trailing_newline': True,
(('table-row',render_table_row),{}), 'same_tag_closes': True
(('tr',render_table_row),{}), }
(('table-header',render_table_header),{}), ),
(('th',render_table_header),{}), (
(('table-data',render_table_data),{}), ('wiki', render_wiki_link),
(('td',render_table_data),{}), {
(('youtube',render_youtube_video),{'same_tag_closes':True}), 'strip': True,
'swallow_tailin_newline': True,
'standalone': True
}
),
(
('codeblock', render_codeblock),
{
'strip': True,
'swallow_trailing_newline': False,
'same_tag_closes': False,
'render_embedded': False
}
),
(('ol', render_ordered_list), {}),
(('ul', render_unordered_list), {}),
(('li', render_list_item), {}),
(('p', render_paragraph), {'same_tag_closes': False}),
(('image', render_image), {'same_tag_closes': True}),
(('img', render_image), {'same_tag_closes': True}),
(('wiki-image', render_wiki_image), {'standalone': True}),
(('wimg', render_wiki_image),{'standalone': True}),
(('table', render_table), {}),
(('table-row', render_table_row), {}),
(('tr', render_table_row), {}),
(('table-header', render_table_header), {}),
(('th', render_table_header), {}),
(('table-data', render_table_data), {}),
(('td', render_table_data), {}),
(('youtube', render_youtube_video), {'same_tag_closes': True}),
] ]

View File

@@ -7,21 +7,23 @@ from ... import settings
from ... import models from ... import models
import bbcode import bbcode
def render_url(tag_name:str,value,options,parent,context): def render_url(tag_name:str,value,options,parent,context):
try: try:
url = options['url'] url = options['url']
except KeyError: except KeyError:
url = value url = value
if not url.startswith('/') and '://' not in url: if not url.startswith('/') and '://' not in url:
url = "http://" + url url = "http://" + url
if settings.USE_BOOTSTRAP: if settings.USE_BOOTSTRAP:
if ['noicon in options']: if ['noicon in options']:
return f"<a href=\"{url}\" referrer-policy=\"no-referrer\" rel=\"noreferrer noopener\">{value}</a>" return f"<a href=\"{url}\" referrer-policy=\"no-referrer\" rel=\"noreferrer noopener\">{value}</a>"
return f"<a href=\"{url}\" class=\"icon-link icon-link-hover\" referrer-policy=\"no-referrer\" rel=\"noreferrer noopener\">{value}<svg class=\"bi\"><use xlink:href=\"{settings.settings.STATIC_URL + "tinywiki/icons/bootstrap-icons.svg"}#box-arrow-up-right\"></use></svg></a>" return f"<a href=\"{url}\" class=\"icon-link icon-link-hover\" referrer-policy=\"no-referrer\" rel=\"noreferrer noopener\">{value}<svg class=\"bi\"><use xlink:href=\"{settings.settings.STATIC_URL + "tinywiki/icons/bootstrap-icons.svg"}#box-arrow-up-right\"></use></svg></a>"
return f"<a href=\"{url}\" referrer-policy=\"no-referrer\" rel=\"noreferrer noopener\">{value}</a>" return f"<a href=\"{url}\" referrer-policy=\"no-referrer\" rel=\"noreferrer noopener\">{value}</a>"
def render_wiki_url(tag_name,value,options,parent,context): def render_wiki_url(tag_name,value,options,parent,context):
if tag_name in options: if tag_name in options:
url = reverse("tinywiki:page",kwargs={'slug':options[tag_name]}) url = reverse("tinywiki:page",kwargs={'slug':options[tag_name]})
@@ -30,11 +32,11 @@ def render_wiki_url(tag_name,value,options,parent,context):
page = models.Page.objects.get(slug=slug) page = models.Page.objects.get(slug=slug)
except models.Page.DoesNotExist: except models.Page.DoesNotExist:
page = None page = None
else: else:
url = reverse('tinywiki:home') url = reverse('tinywiki:home')
slug=None slug=None
if settings.USE_BOOTSTRAP: if settings.USE_BOOTSTRAP:
href = settings.settings.STATIC_URL+"tinywiki/icons/bootstrap-icons.svg" href = settings.settings.STATIC_URL+"tinywiki/icons/bootstrap-icons.svg"
if page: if page:
@@ -69,61 +71,66 @@ def render_wiki_link(tag_name,value,options,parent,context):
title = _("Home") title = _("Home")
url = reverse("tinywiki:home") url = reverse("tinywiki:home")
svg = "house" svg = "house"
if settings.USE_BOOTSTRAP: if settings.USE_BOOTSTRAP:
href = settings.settings.STATIC_URL + "tinywiki/icons/bootstrap-icons.svg" href = settings.settings.STATIC_URL + "tinywiki/icons/bootstrap-icons.svg"
return f"<a href=\"{url}\" class=\"icon-link icon-link-hover\">{title}<svg class=\"bi\"><use xlink:href=\"{href}#{svg}\"></use></svg></a>" return f"<a href=\"{url}\" class=\"icon-link icon-link-hover\">{title}<svg class=\"bi\"><use xlink:href=\"{href}#{svg}\"></use></svg></a>"
return f"<a href=\"{url}\">{value}</a>" return f"<a href=\"{url}\">{value}</a>"
def render_codeblock(tag_name:str,value,options,parent,context)->str: def render_codeblock(tag_name:str,value,options,parent,context)->str:
if tag_name in options: if tag_name in options:
return f"<pre style=\"overflow-x:auto;\"><code class=\"language-{options[tag_name]}\">{value}</pre></code>" return f"<pre style=\"overflow-x:auto;\"><code class=\"language-{options[tag_name]}\">{value}</pre></code>"
return f"<pre style=\"overflow-x:auto;\"><code>{value}</pre></code>" return f"<pre style=\"overflow-x:auto;\"><code>{value}</pre></code>"
def render_ordered_list(tag_name:str,value,options,parent,context)->str: def render_ordered_list(tag_name:str,value,options,parent,context)->str:
return f"<ol>{value}</ol>" return f"<ol>{value}</ol>"
def render_unordered_list(tag_name:str,value,options,parent,context)->str: def render_unordered_list(tag_name:str,value,options,parent,context)->str:
return f"<ul>{value}</ul>" return f"<ul>{value}</ul>"
def render_list_item(tag_name:str,value,options,parent,context)->str: def render_list_item(tag_name:str,value,options,parent,context)->str:
return f"<li>{value}</li>" return f"<li>{value}</li>"
def render_paragraph(tag_name:str,value,options,parent,context):
def render_paragraph(tag_name: str, value, options, parent, context):
if settings.USE_BOOTSTRAP: if settings.USE_BOOTSTRAP:
return f"<p style=\"text-align:justify;\">{value}</p>" return f"<p style=\"text-align:justify;\">{value}</p>"
return f"<p>{value}</p>" return f"<p>{value}</p>"
def render_image(tag_name:str,value,options,parent,context):
def render_image(tag_name: str, value, options, parent, context):
if tag_name not in options: if tag_name not in options:
return "" return ""
if 'alt' in options: if 'alt' in options:
alt=options['alt'] alt = options['alt']
else: else:
alt="" alt = ""
if settings.USE_BOOTSTRAP: if settings.USE_BOOTSTRAP:
classes=["img-fluid","figure-img","rounded"] classes = ["img-fluid", "figure-img", "rounded"]
fig_classes=["figure","my-1"] fig_classes = ["figure", "my-1"]
styles=[] styles = []
fig_styles=[] fig_styles = []
else: else:
styles=["max-width:100%;"] styles = ["max-width:100%;"]
classes=[] classes = []
fig_classes=[] fig_classes = []
fig_styles=[] fig_styles = []
if 'width' in options: if 'width' in options:
_w = options['width'] _w = options['width']
if _w.endswith('px') or _w.endswith('em') or _w.endswith('rem'): if _w.endswith('px') or _w.endswith('em') or _w.endswith('rem'):
fig_styles.append(f"width:{_w};") fig_styles.append(f"width:{_w};")
else: else:
if _w.endswith('%'): if _w.endswith('%'):
_w = _w[:-1] _w = _w[:-1]
if _w.isdigit(): if _w.isdigit():
_w=int(_w) _w = int(_w)
if _w > 100: if _w > 100:
_w = 100 _w = 100
if settings.USE_BOOTSTRAP: if settings.USE_BOOTSTRAP:
@@ -138,7 +145,7 @@ def render_image(tag_name:str,value,options,parent,context):
_h = options['width'] _h = options['width']
if _h.endswith('px') or _h.endswith('em') or _h.endswith('rem'): if _h.endswith('px') or _h.endswith('em') or _h.endswith('rem'):
fig_styles.append(f"height:{_h};") fig_styles.append(f"height:{_h};")
else: else:
if _h.endswith('%'): if _h.endswith('%'):
_h= _h[:-1] _h= _h[:-1]
if _h.isdigit(): if _h.isdigit():
@@ -152,15 +159,15 @@ def render_image(tag_name:str,value,options,parent,context):
height = ((_h // 25) * 25) height = ((_h // 25) * 25)
if height > 100: if height > 100:
height = 100 height = 100
fig_classes.append(f'h-{height}') fig_classes.append(f'h-{height}')
else: else:
fig_styles.append(f"height:{_h}%;") fig_styles.append(f"height:{_h}%;")
if "position" in options: if "position" in options:
pos = options['position'] pos = options['position']
if settings.USE_BOOTSTRAP: if settings.USE_BOOTSTRAP:
if pos == "left" or pos=="start": if pos == "left" or pos == "start":
fig_classes += ["float-start","me-2"] fig_classes += ["float-start","me-2"]
classes += ["float-start","me-2"] classes += ["float-start","me-2"]
elif pos == "right" or pos == "end": elif pos == "right" or pos == "end":
@@ -169,46 +176,47 @@ def render_image(tag_name:str,value,options,parent,context):
elif pos == "center": elif pos == "center":
fig_classes += ["mx-auto","d-block"] fig_classes += ["mx-auto","d-block"]
classes += ["mx-auto","d-block"] classes += ["mx-auto","d-block"]
if styles: if styles:
style=f"style=\"{"".join(styles)}\"" style = f"style=\"{"".join(styles)}\""
else: else:
style="" style = ""
if fig_styles: if fig_styles:
fig_style=f'style="{"".join(fig_styles)}"' fig_style = f'style="{"".join(fig_styles)}"'
else: else:
fig_style="" fig_style = ""
if settings.USE_BOOTSTRAP: if settings.USE_BOOTSTRAP:
return f'<figure class="{" ".join(fig_classes)} {fig_style}"><img src="{options[tag_name]}" class="{' '.join(classes)}" alt="{alt}" {style}><figcaption class="figure-caption text-end">{ value }</figcaption></figure>' return f'<figure class="{" ".join(fig_classes)} {fig_style}"><img src="{options[tag_name]}" class="{' '.join(classes)}" alt="{alt}" {style}><figcaption class="figure-caption text-end">{ value }</figcaption></figure>'
else: else:
return f'<figure {fig_style}><img src="{options[tag_name]}" {style}><figcaption>{value}</figcaption></figure>' return f'<figure {fig_style}><img src="{options[tag_name]}" {style}><figcaption>{value}</figcaption></figure>'
def render_wiki_image(tag_name:str,value,options,parent,context):
def render_wiki_image(tag_name: str, value, options, parent, context):
if tag_name not in options: if tag_name not in options:
return "" return ""
try: try:
image = models.Image.objects.get(slug=options[tag_name]) image = models.Image.objects.get(slug=options[tag_name])
except models.Image.DoesNotExist: except models.Image.DoesNotExist:
return "" return ""
if settings.USE_BOOTSTRAP: if settings.USE_BOOTSTRAP:
classes=["img-fluid","figure-img","rounded"] classes = ["img-fluid","figure-img","rounded"]
fig_classes=["figure","my-1"] fig_classes = ["figure","my-1"]
styles=[] styles = []
fig_styles=[] fig_styles = []
else: else:
styles=["max-width:100%;"] styles = ["max-width:100%;"]
classes=[] classes = []
fig_classes=[] fig_classes = []
fig_styles=[] fig_styles = []
if 'width' in options: if 'width' in options:
_w = options['width'] _w = options['width']
if _w.endswith('px') or _w.endswith('em') or _w.endswith('rem'): if _w.endswith('px') or _w.endswith('em') or _w.endswith('rem'):
fig_styles.append(f"width:{_w};") fig_styles.append(f"width:{_w};")
else: else:
if _w.endswith('%'): if _w.endswith('%'):
_w = _w[:-1] _w = _w[:-1]
if _w.isdigit(): if _w.isdigit():
@@ -227,7 +235,7 @@ def render_wiki_image(tag_name:str,value,options,parent,context):
_h = options['width'] _h = options['width']
if _h.endswith('px') or _h.endswith('em') or _h.endswith('rem'): if _h.endswith('px') or _h.endswith('em') or _h.endswith('rem'):
fig_styles.append(f"height:{_h};") fig_styles.append(f"height:{_h};")
else: else:
if _h.endswith('%'): if _h.endswith('%'):
_h= _h[:-1] _h= _h[:-1]
if _h.isdigit(): if _h.isdigit():
@@ -241,11 +249,11 @@ def render_wiki_image(tag_name:str,value,options,parent,context):
height = ((_h // 25) * 25) height = ((_h // 25) * 25)
if height > 100: if height > 100:
height = 100 height = 100
fig_classes.append(f'h-{height}') fig_classes.append(f'h-{height}')
else: else:
fig_styles.append(f"height:{_h}%;") fig_styles.append(f"height:{_h}%;")
if "position" in options: if "position" in options:
pos = options['position'] pos = options['position']
if settings.USE_BOOTSTRAP: if settings.USE_BOOTSTRAP:
@@ -255,22 +263,23 @@ def render_wiki_image(tag_name:str,value,options,parent,context):
fig_classes += ["float-end","ms-2"] fig_classes += ["float-end","ms-2"]
elif pos == "center": elif pos == "center":
fig_classes += ["mx-auto","d-block"] fig_classes += ["mx-auto","d-block"]
if styles: if styles:
style=f"style=\"{"".join(styles)}\"" style=f"style=\"{"".join(styles)}\""
else: else:
style="" style=""
if fig_styles: if fig_styles:
fig_style=f'style="{"".join(fig_styles)}"' fig_style=f'style="{"".join(fig_styles)}"'
else: else:
fig_style="" fig_style=""
if settings.USE_BOOTSTRAP: if settings.USE_BOOTSTRAP:
return f'<figure class="{" ".join(fig_classes)}" {fig_style}><img src="{image.image.url}" alt="{image.alt}" class="{' '.join(classes)}" {style}><figcaption class="figure-caption text-end">{image.description_html}</figcaption></figure>' return f'<figure class="{" ".join(fig_classes)}" {fig_style}><img src="{image.image.url}" alt="{image.alt}" class="{' '.join(classes)}" {style}><figcaption class="figure-caption text-end">{image.description_html}</figcaption></figure>'
else: else:
return f'<figure {fig_style}><img src="{image.image.url}" alt="{image.alt}" {style}><figcaption>{image.description}</figcaption></figure>' return f'<figure {fig_style}><img src="{image.image.url}" alt="{image.alt}" {style}><figcaption>{image.description}</figcaption></figure>'
def render_table(tag_name:str,value,options,parent,context): def render_table(tag_name:str,value,options,parent,context):
if settings.USE_BOOTSTRAP: if settings.USE_BOOTSTRAP:
classes=["table"] classes=["table"]
@@ -279,13 +288,13 @@ def render_table(tag_name:str,value,options,parent,context):
classes.append("table-bordered") classes.append("table-bordered")
if options["bordered"] in ("primary","secondary","info","warning","danger","success","light","dark"): if options["bordered"] in ("primary","secondary","info","warning","danger","success","light","dark"):
classes.append(f"border-{options['bordered']}") classes.append(f"border-{options['bordered']}")
if tag_name in options: if tag_name in options:
if options[tag_name] in ("primary","secondary","info","warning","danger","success","light","dark"): if options[tag_name] in ("primary","secondary","info","warning","danger","success","light","dark"):
classes.append(f"table-{options[tag_name]}") classes.append(f"table-{options[tag_name]}")
return f"<table class=\"{" ".join(classes)}\">{value}</table>" return f"<table class=\"{" ".join(classes)}\">{value}</table>"
return f"<table>{value}</table>" return f"<table>{value}</table>"
def render_table_row(tag_name:str,value,options,parent,context): def render_table_row(tag_name:str,value,options,parent,context):
@@ -322,37 +331,37 @@ def render_table_data(tag_name:str,value,options,parent,context):
if tag_name in options: if tag_name in options:
if options[tag_name] in ("primary","secondary","info","warning","danger","success","light","dark"): if options[tag_name] in ("primary","secondary","info","warning","danger","success","light","dark"):
classes.append(f"table-{options[tag_name]}") classes.append(f"table-{options[tag_name]}")
class_attr=f"class=\"{" ".join(classes)}\"" if classes else "" class_attr = f"class=\"{" ".join(classes)}\"" if classes else ""
return f"<td {class_attr} {" ".join(extra_attributes)}>{value}</td>" return f"<td {class_attr} {" ".join(extra_attributes)}>{value}</td>"
def render_youtube_video(tag_name:str,value,options,parent,context): def render_youtube_video(tag_name: str, value, options, parent, context):
if tag_name not in options: if tag_name not in options:
return "" return ""
if 'alt' in options: if 'alt' in options:
alt=options['alt'] alt = options['alt']
else: else:
alt="" alt = ""
if settings.USE_BOOTSTRAP: if settings.USE_BOOTSTRAP:
styles=[] styles = []
classes=["w-100"] classes = ["w-100"]
div_classes=["my-1"] div_classes = ["my-1"]
div_styles=[] div_styles = []
else: else:
styles=["max-width:100%;"] styles = ["max-width:100%;"]
classes=[] classes = []
div_classes=[] div_classes = []
div_styles=[] div_styles = []
if 'width' in options: if 'width' in options:
_w = options['width'] _w = options['width']
if _w.endswith('px') or _w.endswith('em') or _w.endswith('rem'): if _w.endswith('px') or _w.endswith('em') or _w.endswith('rem'):
if settings.USE_BOOTSTRAP: if settings.USE_BOOTSTRAP:
div_styles.append(f"width:{_w};") div_styles.append(f"width:{_w};")
styles.append(f"width:{_w};") styles.append(f"width:{_w};")
else: else:
if _w.endswith('%'): if _w.endswith('%'):
_w = _w[:-1] _w = _w[:-1]
if _w.isdigit(): if _w.isdigit():
@@ -374,7 +383,7 @@ def render_youtube_video(tag_name:str,value,options,parent,context):
div_styles.append(f"height:{_h};") div_styles.append(f"height:{_h};")
else: else:
styles.append(f"height:{_h};") styles.append(f"height:{_h};")
else: else:
if _h.endswith('%'): if _h.endswith('%'):
_h= _h[:-1] _h= _h[:-1]
if _h.isdigit(): if _h.isdigit():
@@ -388,11 +397,11 @@ def render_youtube_video(tag_name:str,value,options,parent,context):
height = ((_h // 25) * 25) height = ((_h // 25) * 25)
if height > 100: if height > 100:
height = 100 height = 100
div_classes.append(f'h-{height}') div_classes.append(f'h-{height}')
else: else:
styles.append(f"height:{_h}%;") styles.append(f"height:{_h}%;")
if "position" in options: if "position" in options:
pos = options['position'] pos = options['position']
if settings.USE_BOOTSTRAP: if settings.USE_BOOTSTRAP:
@@ -405,16 +414,16 @@ def render_youtube_video(tag_name:str,value,options,parent,context):
elif pos == "center": elif pos == "center":
div_classes += ["mx-auto","d-block"] div_classes += ["mx-auto","d-block"]
#classes += ["mx-auto","d-block"] #classes += ["mx-auto","d-block"]
if styles: if styles:
style=f"style=\"{"".join(styles)}\"" style = f"style=\"{"".join(styles)}\""
else: else:
style="" style = ""
if div_styles: if div_styles:
div_style=f'style="{"".join(div_styles)}"' div_style = f'style="{"".join(div_styles)}"'
else: else:
div_style="" div_style = ""
if settings.USE_BOOTSTRAP: if settings.USE_BOOTSTRAP:
return f'<div class=""{' '.join(div_classes)}" {div_style}><iframe class={" ".join(classes)}" src="https://www.youtube.com/embed/{options[tag_name]}" allowfullscreen></iframe></div>' return f'<div class=""{' '.join(div_classes)}" {div_style}><iframe class={" ".join(classes)}" src="https://www.youtube.com/embed/{options[tag_name]}" allowfullscreen></iframe></div>'
else: else:

View File

@@ -32,4 +32,4 @@
{% block extra_scripts %} {% block extra_scripts %}
<script>hljs.highlightAll();</script> <script>hljs.highlightAll();</script>
{% endblock %} {% endblock %}