markdown: allow positioning attributes on images
New attributes * left, center, right: Exactly what you expect * float-left, float-right: Also just what you expect Currently there is no way to force a clear.
This commit is contained in:
parent
e9c1f04f42
commit
48d6c1c03c
|
@ -120,6 +120,24 @@ input[type="submit"]:focus {
|
|||
.bg-warn:active {
|
||||
background: var(--warn-active);
|
||||
}
|
||||
img.align-left {
|
||||
text-align: left;
|
||||
}
|
||||
img.align-center {
|
||||
display: block;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
}
|
||||
img.align-right {
|
||||
display: block;
|
||||
margin-left: auto;
|
||||
}
|
||||
.float-left {
|
||||
float: left;
|
||||
}
|
||||
.float-right {
|
||||
float: right;
|
||||
}
|
||||
.skip-to-content-link {
|
||||
height: 30px;
|
||||
left: 50%;
|
||||
|
|
|
@ -117,6 +117,25 @@ section {
|
|||
}
|
||||
}
|
||||
|
||||
img.align-left {
|
||||
text-align: left;
|
||||
}
|
||||
img.align-center {
|
||||
display: block;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
}
|
||||
img.align-right {
|
||||
display: block;
|
||||
margin-left: auto;
|
||||
}
|
||||
.float-left {
|
||||
float: left;
|
||||
}
|
||||
.float-right {
|
||||
float: right;
|
||||
}
|
||||
|
||||
|
||||
.skip-to-content-link {
|
||||
height: 30px;
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
<table class="thread topcomment">
|
||||
<tr>
|
||||
<td class="author">{{ widget_user.profile(comment.author) }}</td>
|
||||
<td><div>{{ comment.text | md }}</div></td>
|
||||
<td class="message"><div>{{ comment.text | md }}</div></td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
|
|
|
@ -15,6 +15,40 @@ class MediaExtension(Extension):
|
|||
media_processor.md = md
|
||||
md.inlinePatterns.register(media_processor, 'media_link', 155)
|
||||
|
||||
class AttrDict:
|
||||
def __init__(self, attrs):
|
||||
self.attrs = attrs
|
||||
|
||||
def has(self, name):
|
||||
return name in self.attrs
|
||||
|
||||
def getString(self, name):
|
||||
for attr in self.attrs:
|
||||
if attr.startswith(name + "="):
|
||||
return attr[len(name)+1:]
|
||||
|
||||
def getInt(self, name):
|
||||
try:
|
||||
s = self.getString(name)
|
||||
return int(s) if s is not None else None
|
||||
except ValueError:
|
||||
return None
|
||||
|
||||
def getSize(self, name):
|
||||
s = self.getString(name)
|
||||
if s is None:
|
||||
return None, None
|
||||
dims = s.split("x", 1)
|
||||
try:
|
||||
if len(dims) == 1:
|
||||
return int(dims[0]), None
|
||||
else:
|
||||
w = int(dims[0]) if dims[0] else None
|
||||
h = int(dims[1]) if dims[1] else None
|
||||
return w, h
|
||||
except ValueError:
|
||||
return None, None
|
||||
|
||||
class AttributeLinkInlineProcessor(LinkInlineProcessor):
|
||||
"""
|
||||
A LinkInlineProcessor which additionally supports attributes after links,
|
||||
|
@ -30,7 +64,7 @@ class AttributeLinkInlineProcessor(LinkInlineProcessor):
|
|||
current_attr_text = ""
|
||||
|
||||
if index >= len(data) or data[index] != '{':
|
||||
return [], index, True
|
||||
return AttrDict([]), index, True
|
||||
index += 1
|
||||
|
||||
for pos in range(index, len(data)):
|
||||
|
@ -60,25 +94,7 @@ class AttributeLinkInlineProcessor(LinkInlineProcessor):
|
|||
if current_attr_text:
|
||||
attrs.append(current_attr_text)
|
||||
|
||||
return attrs, index, has_closing_brace
|
||||
|
||||
@staticmethod
|
||||
def hasAttribute(attrs, name):
|
||||
return name in attrs
|
||||
|
||||
@staticmethod
|
||||
def getStringAttribute(attrs, name):
|
||||
for attr in attrs:
|
||||
if attr.startswith(name + "="):
|
||||
return attr[len(name)+1:]
|
||||
|
||||
@staticmethod
|
||||
def getIntAttribute(attrs, name):
|
||||
try:
|
||||
s = AttributeLinkInlineProcessor.getStringAttribute(attrs, name)
|
||||
return int(s) if s is not None else None
|
||||
except ValueError:
|
||||
return None
|
||||
return AttrDict(attrs), index, has_closing_brace
|
||||
|
||||
class MediaInlineProcessor(AttributeLinkInlineProcessor):
|
||||
""" Return a media element from the given match. """
|
||||
|
@ -90,21 +106,6 @@ class MediaInlineProcessor(AttributeLinkInlineProcessor):
|
|||
def isAudio(self, url):
|
||||
return url.endswith(".mp3") or url.endswith(".ogg")
|
||||
|
||||
def getSizeAttribute(self, attrs, name):
|
||||
s = self.getStringAttribute(attrs, name)
|
||||
if s is None:
|
||||
return None, None
|
||||
dims = s.split("x", 1)
|
||||
try:
|
||||
if len(dims) == 1:
|
||||
return int(dims[0]), None
|
||||
else:
|
||||
w = int(dims[0]) if dims[0] else None
|
||||
h = int(dims[1]) if dims[1] else None
|
||||
return w, h
|
||||
except ValueError:
|
||||
return None, None
|
||||
|
||||
def handleMatch(self, m, data):
|
||||
text, index, handled = self.getText(data, m.end(0))
|
||||
if not handled:
|
||||
|
@ -117,19 +118,31 @@ class MediaInlineProcessor(AttributeLinkInlineProcessor):
|
|||
attrs, index, handled = self.getAttributes(data, index)
|
||||
if not handled:
|
||||
return None, None, None
|
||||
print(attrs, self.getSizeAttribute(attrs, "size"))
|
||||
|
||||
kind = "image"
|
||||
if self.hasAttribute(attrs, "audio") or self.isAudio(src):
|
||||
if attrs.has("audio") or self.isAudio(src):
|
||||
kind = "audio"
|
||||
elif self.hasAttribute(attrs, "video") or self.isVideo(src):
|
||||
elif attrs.has("video") or self.isVideo(src):
|
||||
kind = "video"
|
||||
|
||||
# Images
|
||||
|
||||
if kind == "image":
|
||||
w, h = self.getSizeAttribute(attrs, "size")
|
||||
pixelated = self.hasAttribute(attrs, "pixelated")
|
||||
w, h = attrs.getSize("size")
|
||||
class_ = ""
|
||||
# TODO: Media converter: Find a way to clear atfer a float
|
||||
if attrs.has("pixelated"):
|
||||
class_ += " pixelated"
|
||||
if attrs.has("left"):
|
||||
class_ += " align-left"
|
||||
if attrs.has("center"):
|
||||
class_ += " align-center"
|
||||
elif attrs.has("right"):
|
||||
class_ += " align-right"
|
||||
elif attrs.has("float-left"):
|
||||
class_ += " float-left"
|
||||
elif attrs.has("float-right"):
|
||||
class_ += " float-right"
|
||||
|
||||
el = etree.Element("img")
|
||||
el.set("src", src)
|
||||
|
@ -137,8 +150,8 @@ class MediaInlineProcessor(AttributeLinkInlineProcessor):
|
|||
if title is not None:
|
||||
el.set("title", title)
|
||||
|
||||
if pixelated:
|
||||
el.set("class", "pixelated")
|
||||
if class_ != "":
|
||||
el.set("class", class_)
|
||||
if w is not None:
|
||||
el.set("width", str(w))
|
||||
if h is not None:
|
||||
|
|
Loading…
Reference in New Issue