put images in their own lane
This commit is contained in:
@ -2,7 +2,7 @@ from .babycode_parser import Parser
|
|||||||
from markupsafe import escape
|
from markupsafe import escape
|
||||||
import re
|
import re
|
||||||
|
|
||||||
BABYCODE_VERSION = 1
|
BABYCODE_VERSION = 2
|
||||||
|
|
||||||
NAMED_COLORS = [
|
NAMED_COLORS = [
|
||||||
'black', 'silver', 'gray', 'white', 'maroon', 'red',
|
'black', 'silver', 'gray', 'white', 'maroon', 'red',
|
||||||
@ -35,7 +35,19 @@ NAMED_COLORS = [
|
|||||||
'violet', 'wheat', 'white', 'whitesmoke', 'yellow', 'yellowgreen',
|
'violet', 'wheat', 'white', 'whitesmoke', 'yellow', 'yellowgreen',
|
||||||
]
|
]
|
||||||
|
|
||||||
def tag_code(children, attr):
|
def is_tag(e, tag):
|
||||||
|
if e is None:
|
||||||
|
return False
|
||||||
|
if isinstance(e, str):
|
||||||
|
return False
|
||||||
|
if e['type'] != 'bbcode':
|
||||||
|
return False
|
||||||
|
return e['name'] == tag
|
||||||
|
|
||||||
|
def is_text(e):
|
||||||
|
return isinstance(e, str)
|
||||||
|
|
||||||
|
def tag_code(children, attr, surrounding):
|
||||||
is_inline = children.find('\n') == -1
|
is_inline = children.find('\n') == -1
|
||||||
if is_inline:
|
if is_inline:
|
||||||
return f"<code class=\"inline-code\">{children}</code>"
|
return f"<code class=\"inline-code\">{children}</code>"
|
||||||
@ -49,7 +61,7 @@ def tag_list(children):
|
|||||||
list_body = re.sub(r"\n\n+", "\1", list_body)
|
list_body = re.sub(r"\n\n+", "\1", list_body)
|
||||||
return " ".join([f"<li>{x}</li>" for x in list_body.split("\1") if x])
|
return " ".join([f"<li>{x}</li>" for x in list_body.split("\1") if x])
|
||||||
|
|
||||||
def tag_color(children, attr):
|
def tag_color(children, attr, surrounding):
|
||||||
hex_re = r"^#?([0-9a-f]{6}|[0-9a-f]{3})$"
|
hex_re = r"^#?([0-9a-f]{6}|[0-9a-f]{3})$"
|
||||||
potential_color = attr.lower().strip()
|
potential_color = attr.lower().strip()
|
||||||
|
|
||||||
@ -63,31 +75,39 @@ def tag_color(children, attr):
|
|||||||
# return just the way it was if we can't parse it
|
# return just the way it was if we can't parse it
|
||||||
return f"[color={attr}]{children}[/color]"
|
return f"[color={attr}]{children}[/color]"
|
||||||
|
|
||||||
def tag_spoiler(children, attr):
|
def tag_spoiler(children, attr, surrounding):
|
||||||
spoiler_name = attr if attr else "Spoiler"
|
spoiler_name = attr if attr else "Spoiler"
|
||||||
content = f"<div class='accordion-content post-accordion-content hidden'>{children}</div>"
|
content = f"<div class='accordion-content post-accordion-content hidden'>{children}</div>"
|
||||||
container = f"""<div class='accordion hidden'><div class='accordion-header'><button type='button' class='accordion-toggle'>+</button><span>{spoiler_name}</span></div>{content}</div>"""
|
container = f"""<div class='accordion hidden'><div class='accordion-header'><button type='button' class='accordion-toggle'>+</button><span>{spoiler_name}</span></div>{content}</div>"""
|
||||||
return container
|
return container
|
||||||
|
|
||||||
|
def tag_image(children, attr, surrounding):
|
||||||
|
img = f"<img class=\"post-image\" src=\"{attr}\" alt=\"{children}\">"
|
||||||
|
if not is_tag(surrounding[0], 'img'):
|
||||||
|
img = f"<div class=post-img-container>{img}"
|
||||||
|
if not is_tag(surrounding[1], 'img'):
|
||||||
|
img = f"{img}</div>"
|
||||||
|
return img
|
||||||
|
|
||||||
TAGS = {
|
TAGS = {
|
||||||
"b": lambda children, attr: f"<strong>{children}</strong>",
|
"b": lambda children, attr, _: f"<strong>{children}</strong>",
|
||||||
"i": lambda children, attr: f"<em>{children}</em>",
|
"i": lambda children, attr, _: f"<em>{children}</em>",
|
||||||
"s": lambda children, attr: f"<del>{children}</del>",
|
"s": lambda children, attr, _: f"<del>{children}</del>",
|
||||||
"u": lambda children, attr: f"<u>{children}</u>",
|
"u": lambda children, attr, _: f"<u>{children}</u>",
|
||||||
|
|
||||||
"img": lambda children, attr: f"<div class=\"post-img-container\"><img class=\"block-img\" src=\"{attr}\" alt=\"{children}\"></div>",
|
"img": tag_image,
|
||||||
"url": lambda children, attr: f"<a href={attr}>{children}</a>",
|
"url": lambda children, attr, _: f"<a href={attr}>{children}</a>",
|
||||||
"quote": lambda children, attr: f"<blockquote>{children}</blockquote>",
|
"quote": lambda children, attr, _: f"<blockquote>{children}</blockquote>",
|
||||||
"code": tag_code,
|
"code": tag_code,
|
||||||
"ul": lambda children, attr: f"<ul>{tag_list(children)}</ul>",
|
"ul": lambda children, attr, _: f"<ul>{tag_list(children)}</ul>",
|
||||||
"ol": lambda children, attr: f"<ol>{tag_list(children)}</ol>",
|
"ol": lambda children, attr, _: f"<ol>{tag_list(children)}</ol>",
|
||||||
|
|
||||||
"big": lambda children, attr: f"<span style='font-size: 2rem;'>{children}</span>",
|
"big": lambda children, attr, _: f"<span style='font-size: 2rem;'>{children}</span>",
|
||||||
"small": lambda children, attr: f"<span style='font-size: 0.75rem;'>{children}</span>",
|
"small": lambda children, attr, _: f"<span style='font-size: 0.75rem;'>{children}</span>",
|
||||||
"color": tag_color,
|
"color": tag_color,
|
||||||
|
|
||||||
"center": lambda children, attr: f"<div style='text-align: center;'>{children}</div>",
|
"center": lambda children, attr, _: f"<div style='text-align: center;'>{children}</div>",
|
||||||
"right": lambda children, attr: f"<div style='text-align: right;'>{children}</div>",
|
"right": lambda children, attr, _: f"<div style='text-align: right;'>{children}</div>",
|
||||||
|
|
||||||
"spoiler": tag_spoiler,
|
"spoiler": tag_spoiler,
|
||||||
}
|
}
|
||||||
@ -156,9 +176,8 @@ def babycode_to_html(s):
|
|||||||
parser.valid_emotes = EMOJI.keys()
|
parser.valid_emotes = EMOJI.keys()
|
||||||
|
|
||||||
elements = parser.parse()
|
elements = parser.parse()
|
||||||
# print(elements)
|
|
||||||
out = ""
|
out = ""
|
||||||
def fold(element, nobr):
|
def fold(element, nobr, surrounding):
|
||||||
if isinstance(element, str):
|
if isinstance(element, str):
|
||||||
if nobr:
|
if nobr:
|
||||||
return element
|
return element
|
||||||
@ -167,10 +186,16 @@ def babycode_to_html(s):
|
|||||||
match element['type']:
|
match element['type']:
|
||||||
case "bbcode":
|
case "bbcode":
|
||||||
c = ""
|
c = ""
|
||||||
for child in element['children']:
|
for i in range(len(element['children'])):
|
||||||
|
child = element['children'][i]
|
||||||
|
_surrounding = (
|
||||||
|
element['children'][i - 1] if i-1 >= 0 else None,
|
||||||
|
element['children'][i + 1] if i+1 < len(element['children']) else None
|
||||||
|
)
|
||||||
_nobr = element['name'] == "code" or element['name'] == "ul" or element['name'] == "ol"
|
_nobr = element['name'] == "code" or element['name'] == "ul" or element['name'] == "ol"
|
||||||
c = c + fold(child, _nobr)
|
c = c + fold(child, _nobr, _surrounding)
|
||||||
res = TAGS[element['name']](c, element['attr'])
|
|
||||||
|
res = TAGS[element['name']](c, element['attr'], surrounding)
|
||||||
return res
|
return res
|
||||||
case "link":
|
case "link":
|
||||||
return f"<a href=\"{element['url']}\">{element['url']}</a>"
|
return f"<a href=\"{element['url']}\">{element['url']}</a>"
|
||||||
@ -178,6 +203,13 @@ def babycode_to_html(s):
|
|||||||
return EMOJI[element['name']]
|
return EMOJI[element['name']]
|
||||||
case "rule":
|
case "rule":
|
||||||
return "<hr>"
|
return "<hr>"
|
||||||
for e in elements:
|
# for e in elements:
|
||||||
out = out + fold(e, False)
|
# out = out + fold(e, False)
|
||||||
|
for i in range(len(elements)):
|
||||||
|
e = elements[i]
|
||||||
|
surrounding = (
|
||||||
|
elements[i - 1] if i-1 >= 0 else None,
|
||||||
|
elements[i + 1] if i+1 < len(elements) else None
|
||||||
|
)
|
||||||
|
out = out + fold(e, False, surrounding)
|
||||||
return out
|
return out
|
||||||
|
@ -126,8 +126,8 @@
|
|||||||
<code class="inline-code">[img=https://forum.poto.cafe/avatars/default.webp]the Python logo with a cowboy hat[/img]</code>
|
<code class="inline-code">[img=https://forum.poto.cafe/avatars/default.webp]the Python logo with a cowboy hat[/img]</code>
|
||||||
{{ '[img=/static/avatars/default.webp]the Python logo with a cowboy hat[/img]' | babycode | safe }}
|
{{ '[img=/static/avatars/default.webp]the Python logo with a cowboy hat[/img]' | babycode | safe }}
|
||||||
</p>
|
</p>
|
||||||
<p>Text inside the tag becomes the alt text. The attribute is the image URL.</p>
|
<p>Text inside the tag becomes the alt text. The attribute is the image URL. The text inside the tag will become the image's alt text.</p>
|
||||||
<p>Images will always break up a paragraph and will get scaled down to a maximum of 400px. The text inside the tag will become the image's alt text.</p>
|
<p>Images will always break up a paragraph and will get scaled down to a maximum of 400px. However, if there is no space between consecutive <code class="inline-code">[img]</code> tags, </p>
|
||||||
<p>Multiple images attached to a post can be clicked to open a dialog to view them.</p>
|
<p>Multiple images attached to a post can be clicked to open a dialog to view them.</p>
|
||||||
</section>
|
</section>
|
||||||
<section class="babycode-guide-section">
|
<section class="babycode-guide-section">
|
||||||
|
@ -142,8 +142,22 @@ document.addEventListener("DOMContentLoaded", () => {
|
|||||||
//lightboxes
|
//lightboxes
|
||||||
lightboxObj = constructLightbox();
|
lightboxObj = constructLightbox();
|
||||||
document.body.appendChild(lightboxObj.dialog);
|
document.body.appendChild(lightboxObj.dialog);
|
||||||
const postImages = document.querySelectorAll(".post-inner img.block-img");
|
|
||||||
|
function setImageMaxSize(img) {
|
||||||
|
const { maxWidth: origMaxWidth } = getComputedStyle(img);
|
||||||
|
if (img.naturalWidth >= parseInt(origMaxWidth)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
img.style.maxWidth = img.naturalWidth + "px";
|
||||||
|
}
|
||||||
|
|
||||||
|
const postImages = document.querySelectorAll(".post-inner img.post-image");
|
||||||
postImages.forEach(postImage => {
|
postImages.forEach(postImage => {
|
||||||
|
if (postImage.complete) {
|
||||||
|
setImageMaxSize(postImage);
|
||||||
|
} else {
|
||||||
|
postImage.addEventListener("load", () => setImageMaxSize(postImage));
|
||||||
|
}
|
||||||
const belongingTo = postImage.closest(".post-inner");
|
const belongingTo = postImage.closest(".post-inner");
|
||||||
const images = lightboxImages.get(belongingTo) ?? [];
|
const images = lightboxImages.get(belongingTo) ?? [];
|
||||||
images.push({
|
images.push({
|
||||||
|
@ -511,10 +511,21 @@ input[type=text]:focus, input[type=password]:focus, textarea:focus, select:focus
|
|||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.block-img {
|
.post-img-container {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
gap: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.post-image {
|
||||||
object-fit: contain;
|
object-fit: contain;
|
||||||
max-width: 400px;
|
max-width: 300px;
|
||||||
max-height: 400px;
|
max-height: 300px;
|
||||||
|
min-width: 200px;
|
||||||
|
min-height: 200px;
|
||||||
|
flex: 1 1 0%;
|
||||||
|
width: auto;
|
||||||
|
height: auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
.thread-info-container {
|
.thread-info-container {
|
||||||
|
@ -512,10 +512,21 @@ input[type="text"], input[type="password"], textarea, select {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.block-img {
|
.post-img-container {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
gap: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.post-image {
|
||||||
object-fit: contain;
|
object-fit: contain;
|
||||||
max-width: 400px;
|
max-width: 400px;
|
||||||
max-height: 400px;
|
max-height: 400px;
|
||||||
|
min-width: 200px;
|
||||||
|
min-height: 200px;
|
||||||
|
flex: 1 1 0%;
|
||||||
|
width: auto;
|
||||||
|
height: auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
.thread-info-container {
|
.thread-info-container {
|
||||||
|
Reference in New Issue
Block a user