mirror of https://github.com/zulip/zulip.git
Add inline previews for images and youtube videos.
(imported from commit 13711a7821318c8bff7c483e874756a63d761c15)
This commit is contained in:
parent
ac1c111489
commit
02bf89c3c3
|
@ -11,6 +11,57 @@ from zephyr.lib.bugdown import codehilite, fenced_code
|
|||
from zephyr.lib.bugdown.fenced_code import FENCE_RE
|
||||
from zephyr.lib.timeout import timeout
|
||||
|
||||
class InlineImagePreviewProcessor(markdown.treeprocessors.Treeprocessor):
|
||||
def is_image(self, url):
|
||||
# List from http://support.google.com/chromeos/bin/answer.py?hl=en&answer=183093
|
||||
for ext in [".bmp", ".gif", ".jpg", "jpeg", ".png", ".webp"]:
|
||||
if url.lower().endswith(ext):
|
||||
return True
|
||||
return False
|
||||
|
||||
def youtube_image(self, url):
|
||||
# Youtube video id extraction regular expression from http://pastebin.com/KyKAFv1s
|
||||
# If it matches, match.group(2) is the video id.
|
||||
youtube_re = r'^((?:https?://)?(?:youtu\.be/|(?:\w+\.)?youtube(?:-nocookie)?\.com/)(?:(?:(?:v|embed)/)|(?:(?:watch(?:_popup)?(?:\.php)?)?(?:\?|#!?)(?:.+&)?v=)))?([0-9A-Za-z_-]+)(?(1).+)?$'
|
||||
match = re.match(youtube_re, url)
|
||||
if match is None:
|
||||
return None
|
||||
return "http://i.ytimg.com/vi/%s/default.jpg" % (match.group(2),)
|
||||
|
||||
# Search the tree for <a> tags and read their href values
|
||||
def find_images(self, root):
|
||||
images = []
|
||||
stack = [root]
|
||||
|
||||
while stack:
|
||||
currElement = stack.pop()
|
||||
for child in currElement.getchildren():
|
||||
if child.tag == "a":
|
||||
url = child.get("href")
|
||||
if self.is_image(url):
|
||||
images.append((url, url))
|
||||
else:
|
||||
youtube = self.youtube_image(url)
|
||||
if youtube is not None:
|
||||
images.append((youtube, url))
|
||||
|
||||
if child.getchildren():
|
||||
stack.append(child)
|
||||
return images
|
||||
|
||||
def run(self, root):
|
||||
image_urls = self.find_images(root)
|
||||
for (url, link) in image_urls:
|
||||
a = markdown.util.etree.SubElement(root, "a")
|
||||
a.set("href", link)
|
||||
a.set("target", "_blank")
|
||||
a.set("title", link)
|
||||
img = markdown.util.etree.SubElement(a, "img")
|
||||
img.set("src", url)
|
||||
img.set("class", "message_inline_image")
|
||||
|
||||
return root
|
||||
|
||||
class Gravatar(markdown.inlinepatterns.Pattern):
|
||||
def handleMatch(self, match):
|
||||
img = markdown.util.etree.Element('img')
|
||||
|
@ -203,6 +254,8 @@ class Bugdown(markdown.Extension):
|
|||
BugdownUListPreprocessor(md),
|
||||
"_begin")
|
||||
|
||||
md.treeprocessors.add("inline_images", InlineImagePreviewProcessor(md), "_end")
|
||||
|
||||
_md_engine = markdown.Markdown(
|
||||
safe_mode = 'escape',
|
||||
output_format = 'html',
|
||||
|
|
|
@ -743,6 +743,13 @@ table.floating_recipient {
|
|||
height: 20px;
|
||||
}
|
||||
|
||||
.message_inline_image {
|
||||
margin-bottom: 5px;
|
||||
margin-left: 5px;
|
||||
max-width: 120px;
|
||||
max-height: 100px;
|
||||
}
|
||||
|
||||
.actions_popover a {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
|
|
@ -1892,9 +1892,11 @@ int x = 3
|
|||
"<p>some text %s with extras</p>", 'https://www.google.com/baz_(match)?with=foo&bar=baz'),
|
||||
('hash it http://foo.com/blah_(wikipedia)_blah#cite-1',
|
||||
"<p>hash it %s</p>", 'http://foo.com/blah_(wikipedia)_blah#cite-1'),
|
||||
('http://technet.microsoft.com/en-us/library/Cc751099.rk20_25_big(l=en-us).gif',
|
||||
# This last one was originally a .gif but was changed to .mov
|
||||
# to avoid triggering the inline image preview support
|
||||
('http://technet.microsoft.com/en-us/library/Cc751099.rk20_25_big(l=en-us).mov',
|
||||
"<p>%s</p>",
|
||||
'http://technet.microsoft.com/en-us/library/Cc751099.rk20_25_big(l=en-us).gif')]
|
||||
'http://technet.microsoft.com/en-us/library/Cc751099.rk20_25_big(l=en-us).mov')]
|
||||
|
||||
for inline_url, reference, url in conversions:
|
||||
try:
|
||||
|
@ -1915,6 +1917,18 @@ xxx/xxxxxx%xxxxxx/xx/" target="_blank" title="xxxx://xxxxxxxxx:xxxx/xxx/xxxxxx%x
|
|||
xxxxxxx</strong></p>\n<p>xxxxxxx xxxxx xxxx xxxxx:<br>\n<code>xxxxxx</code>: xxxxxxx<br>\n<code>xxxxxx</code>: xxxxx\
|
||||
<br>\n<code>xxxxxx</code>: xxxxx xxxxx</p>')
|
||||
|
||||
def test_inline_image(self):
|
||||
msg = 'Google logo today: https://www.google.com/images/srpr/logo4w.png\nKinda boring'
|
||||
converted = convert(msg)
|
||||
|
||||
self.assertEqual(converted, '<p>Google logo today: <a href="https://www.google.com/images/srpr/logo4w.png" target="_blank" title="https://www.google.com/images/srpr/logo4w.png">https://www.google.com/images/srpr/logo4w.png</a><br>\nKinda boring</p>\n<a href="https://www.google.com/images/srpr/logo4w.png" target="_blank" title="https://www.google.com/images/srpr/logo4w.png"><img class="message_inline_image" src="https://www.google.com/images/srpr/logo4w.png"></a>')
|
||||
|
||||
def test_inline_youtube(self):
|
||||
msg = 'Check out the debate: http://www.youtube.com/watch?v=hx1mjT73xYE'
|
||||
converted = convert(msg)
|
||||
|
||||
self.assertEqual(converted, '<p>Check out the debate: <a href="http://www.youtube.com/watch?v=hx1mjT73xYE" target="_blank" title="http://www.youtube.com/watch?v=hx1mjT73xYE">http://www.youtube.com/watch?v=hx1mjT73xYE</a></p>\n<a href="http://www.youtube.com/watch?v=hx1mjT73xYE" target="_blank" title="http://www.youtube.com/watch?v=hx1mjT73xYE"><img class="message_inline_image" src="http://i.ytimg.com/vi/hx1mjT73xYE/default.jpg"></a>')
|
||||
|
||||
def test_multiline_strong(self):
|
||||
msg = "Welcome to **the jungle**"
|
||||
converted = convert(msg)
|
||||
|
|
Loading…
Reference in New Issue