prelom/django/uploads/extensions/embed.py

132 lines
5.6 KiB
Python

from django.utils.html import escape
import markdown
import uploads.models
EMBED_RE = r'\[(pdf|img|file):([a-z0-9-]+) ?([^\]]*)\]'
#PDF_EMBED_RE = r'\[pdf:([a-z0-9-]+) ?([^\]]*)\]'
class EmbedPattern(markdown.inlinepatterns.Pattern):
def handleMatch(self, m):
embed_type = m.group(2)
slug = self.unescape(m.group(3))
caption = self.unescape(m.group(4))
if embed_type == 'pdf':
pdf_upload = uploads.models.PdfUpload.objects.filter(slug=slug).first()
if pdf_upload:
# This div structure is messy because it forces the enclosing
# <p> to close first. Ideally, we'd make this a block pattern.
div_el = markdown.util.etree.Element('div')
object_el = markdown.util.etree.SubElement(div_el, 'object')
path = pdf_upload.file.url
object_el.set('data', path)
object_el.set('type', 'application/pdf')
object_el.set('width', '100%')
object_el.set('height', '800px')
iframe_el = markdown.util.etree.SubElement(object_el, "iframe")
iframe_el.set('src', path)
iframe_el.set('width', '100%')
iframe_el.set('height', '800px')
iframe_el.text = 'Please download the PDF'
# Show the PNG version for a mobile fallback.
image_el = markdown.util.etree.SubElement(div_el, 'img')
image_el.set('class', 'mobile-only')
object_el.set('class', 'non-mobile-only')
image_el.set('src', path + '.png')
print_el = markdown.util.etree.SubElement(div_el, 'div')
print_el.set('class', 'print-only')
print_el.text = "Don't print this page, print the PDF itself!"
return div_el
else:
return 'INVALID FILE: ' + slug
elif embed_type == 'img':
image_upload = uploads.models.ImageUpload.objects.filter(slug=slug).first()
if image_upload:
div_el = markdown.util.etree.Element('div')
div_el.set('class' , 'uploaded-image')
span_el = markdown.util.etree.SubElement(div_el, 'span')
span_el.text = caption
image_el = markdown.util.etree.SubElement(div_el, 'img')
image_el.set('src', image_upload.file.url)
return div_el
else:
return 'INVALID FILE: ' + slug
else:
other_upload = uploads.models.OtherUpload.objects.filter(slug=slug).first()
if other_upload:
div_el = markdown.util.etree.Element('div')
div_el.set('class', 'uploaded-file')
a_el = markdown.util.etree.SubElement(div_el, 'a')
a_el.set('class', 'ui large red icon button')
a_el.set('href', other_upload.file.url)
i_el = markdown.util.etree.SubElement(a_el, 'i')
i_el.set('class', 'download icon')
# Using .tail not .text to ensure that it follows the <i>
i_el.tail = 'Download {title} ({ext})'.format(
title=escape(other_upload.title),
ext=other_upload.extension
)
return div_el
else:
return 'INVALID FILE: ' + slug
# For embedding two images side by side.
DOUBLE_EMBED_RE = r'\[img2:([a-z0-9-]+) ([a-z0-9-]+)\]'
class DoubleEmbedPattern(markdown.inlinepatterns.Pattern):
def handleMatch(self, m):
slug_1 = self.unescape(m.group(2))
slug_2 = self.unescape(m.group(3))
image_1 = uploads.models.ImageUpload.objects.filter(slug=slug_1).first()
image_2 = uploads.models.ImageUpload.objects.filter(slug=slug_2).first()
if image_1 and image_2:
div_el = markdown.util.etree.Element('div')
div_el.set('class' , 'uploaded-images')
image_el_1 = markdown.util.etree.SubElement(div_el, 'img')
image_el_1.set('src', image_1.file.url)
image_el_2 = markdown.util.etree.SubElement(div_el, 'img')
image_el_2.set('src', image_2.file.url)
return div_el
else:
invalid_slugs = []
if not image_1:
invalid_slugs.append(slug_1)
if not image_2:
invalid_slugs.append(slug_2)
return 'INVALID FILE: ' + ', '.join(invalid_slugs)
# For embedding 2+ images side by side. Will eventually supersede Double
IMAGE_EMBED_RE = r'\[images:([a-z0-9- ]+)\]'
class ImageEmbedPattern(markdown.inlinepatterns.Pattern):
def handleMatch(self, m):
div_el = markdown.util.etree.Element('div')
div_el.set('class' , 'uploaded-image')
slugs = self.unescape(m.group(2)).split()
for slug in slugs:
image = uploads.models.ImageUpload.objects.filter(slug=slug).first()
# Might want to do this asynchronously to catch all the invalids
if not image:
return 'INVALID FILE: {}'.format(image)
image_el = markdown.util.etree.SubElement(div_el, 'img')
image_el.set('src', image.file.url)
return div_el
class EmbedExtension(markdown.Extension):
def extendMarkdown(self, md, md_globals):
md.inlinePatterns['embed'] = EmbedPattern(EMBED_RE, md)
md.inlinePatterns['double_embed'] = DoubleEmbedPattern(DOUBLE_EMBED_RE, md)
md.inlinePatterns['image_embed'] = ImageEmbedPattern(IMAGE_EMBED_RE, md)
def makeExtension(*args, **kwargs):
return EmbedExtension(*args, **kwargs)