1. Mikhail Korobov
  2. python-markdown-video

Source

python-markdown-video / mdx_video.py

#!/usr/bin/env python

"""
Embeds web videos using URLs.  For instance, if a URL to an youtube video is
found in the text submitted to markdown and it isn't enclosed in parenthesis
like a normal link in markdown, then the URL will be swapped with a embedded
youtube video.

All resulting HTML is XHTML Strict compatible.

>>> import markdown

Test Metacafe

>>> s = "http://www.metacafe.com/watch/yt-tZMsrrQCnx8/pycon_2008_django_sprint_room/"
>>> markdown.markdown(s, ['video'])
u'<p><object data="http://www.metacafe.com/fplayer/yt-tZMsrrQCnx8/pycon_2008_django_sprint_room.swf" height="423" type="application/x-shockwave-flash" width="498"><param name="movie" value="http://www.metacafe.com/fplayer/yt-tZMsrrQCnx8/pycon_2008_django_sprint_room.swf" /><param name="allowFullScreen" value="true" /></object></p>'


Test Metacafe with arguments

>>> markdown.markdown(s, ['video(metacafe_width=500,metacafe_height=425)'])
u'<p><object data="http://www.metacafe.com/fplayer/yt-tZMsrrQCnx8/pycon_2008_django_sprint_room.swf" height="425" type="application/x-shockwave-flash" width="500"><param name="movie" value="http://www.metacafe.com/fplayer/yt-tZMsrrQCnx8/pycon_2008_django_sprint_room.swf" /><param name="allowFullScreen" value="true" /></object></p>'


Test Link To Metacafe

>>> s = "[Metacafe link](http://www.metacafe.com/watch/yt-tZMsrrQCnx8/pycon_2008_django_sprint_room/)"
>>> markdown.markdown(s, ['video'])
u'<p><a href="http://www.metacafe.com/watch/yt-tZMsrrQCnx8/pycon_2008_django_sprint_room/">Metacafe link</a></p>'


Test Markdown Escaping

>>> s = "\\http://www.metacafe.com/watch/yt-tZMsrrQCnx8/pycon_2008_django_sprint_room/"
>>> markdown.markdown(s, ['video'])
u'<p>http://www.metacafe.com/watch/yt-tZMsrrQCnx8/pycon_2008_django_sprint_room/</p>'
>>> s = "`http://www.metacafe.com/watch/yt-tZMsrrQCnx8/pycon_2008_django_sprint_room/`"
>>> markdown.markdown(s, ['video'])
u'<p><code>http://www.metacafe.com/watch/yt-tZMsrrQCnx8/pycon_2008_django_sprint_room/</code></p>'


Test Youtube

>>> s = "http://www.youtube.com/watch?v=u1mA-0w8XPo&feature=PlayList&p=34C6046F7FEACFD3&playnext=1&playnext_from=PL&index=1"
>>> markdown.markdown(s, ['video'])
u'<p><object data="http://www.youtube.com/v/u1mA-0w8XPo" height="344" type="application/x-shockwave-flash" width="425"><param name="movie" value="http://www.youtube.com/v/u1mA-0w8XPo" /><param name="allowFullScreen" value="true" /></object></p>'


Test Youtube with argument

>>> markdown.markdown(s, ['video(youtube_width=200,youtube_height=100)'])
u'<p><object data="http://www.youtube.com/v/u1mA-0w8XPo" height="100" type="application/x-shockwave-flash" width="200"><param name="movie" value="http://www.youtube.com/v/u1mA-0w8XPo" /><param name="allowFullScreen" value="true" /></object></p>'


Test Youtube Link

>>> s = "[Youtube link](http://www.youtube.com/watch?v=u1mA-0w8XPo&feature=PlayList&p=34C6046F7FEACFD3&playnext=1&playnext_from=PL&index=1)"
>>> markdown.markdown(s, ['video'])
u'<p><a href="http://www.youtube.com/watch?v=u1mA-0w8XPo&amp;feature=PlayList&amp;p=34C6046F7FEACFD3&amp;playnext=1&amp;playnext_from=PL&amp;index=1">Youtube link</a></p>'


Test Dailymotion

>>> s = "http://www.dailymotion.com/relevance/search/ut2004/video/x3kv65_ut2004-ownage_videogames"
>>> markdown.markdown(s, ['video'])
u'<p><object data="http://www.dailymotion.com/swf/x3kv65_ut2004-ownage_videogames" height="405" type="application/x-shockwave-flash" width="480"><param name="movie" value="http://www.dailymotion.com/swf/x3kv65_ut2004-ownage_videogames" /><param name="allowFullScreen" value="true" /></object></p>'


Test Dailymotion again (Dailymotion and their crazy URLs)

>>> s = "http://www.dailymotion.com/us/video/x8qak3_iron-man-vs-bruce-lee_fun"
>>> markdown.markdown(s, ['video'])
u'<p><object data="http://www.dailymotion.com/swf/x8qak3_iron-man-vs-bruce-lee_fun" height="405" type="application/x-shockwave-flash" width="480"><param name="movie" value="http://www.dailymotion.com/swf/x8qak3_iron-man-vs-bruce-lee_fun" /><param name="allowFullScreen" value="true" /></object></p>'


Test Yahoo! Video

>>> s = "http://video.yahoo.com/watch/1981791/4769603"
>>> markdown.markdown(s, ['video'])
u'<p><object data="http://d.yimg.com/static.video.yahoo.com/yep/YV_YEP.swf?ver=2.2.40" height="322" type="application/x-shockwave-flash" width="512"><param name="movie" value="http://d.yimg.com/static.video.yahoo.com/yep/YV_YEP.swf?ver=2.2.40" /><param name="allowFullScreen" value="true" /><param name="flashVars" value="id=4769603&amp;vid=1981791" /></object></p>'


Test Veoh Video

>>> s = "http://www.veoh.com/search/videos/q/mario#watch%3De129555XxCZanYD"
>>> markdown.markdown(s, ['video'])
u'<p><object data="http://www.veoh.com/videodetails2.swf?permalinkId=e129555XxCZanYD" height="341" type="application/x-shockwave-flash" width="410"><param name="movie" value="http://www.veoh.com/videodetails2.swf?permalinkId=e129555XxCZanYD" /><param name="allowFullScreen" value="true" /></object></p>'


Test Veoh Video Again (More fun URLs)

>>> s = "http://www.veoh.com/group/BigCatRescuers#watch%3Dv16771056hFtSBYEr"
>>> markdown.markdown(s, ['video'])
u'<p><object data="http://www.veoh.com/videodetails2.swf?permalinkId=v16771056hFtSBYEr" height="341" type="application/x-shockwave-flash" width="410"><param name="movie" value="http://www.veoh.com/videodetails2.swf?permalinkId=v16771056hFtSBYEr" /><param name="allowFullScreen" value="true" /></object></p>'


Test Veoh Video Yet Again (Even more fun URLs)

>>> s = "http://www.veoh.com/browse/videos/category/anime/watch/v181645607JyXPWcQ"
>>> markdown.markdown(s, ['video'])
u'<p><object data="http://www.veoh.com/videodetails2.swf?permalinkId=v181645607JyXPWcQ" height="341" type="application/x-shockwave-flash" width="410"><param name="movie" value="http://www.veoh.com/videodetails2.swf?permalinkId=v181645607JyXPWcQ" /><param name="allowFullScreen" value="true" /></object></p>'


Test Vimeo Video

>>> s = "http://www.vimeo.com/1496152"
>>> markdown.markdown(s, ['video'])
u'<p><object data="http://vimeo.com/moogaloop.swf?clip_id=1496152&amp;amp;server=vimeo.com" height="321" type="application/x-shockwave-flash" width="400"><param name="movie" value="http://vimeo.com/moogaloop.swf?clip_id=1496152&amp;amp;server=vimeo.com" /><param name="allowFullScreen" value="true" /></object></p>'

Test Vimeo Video with some GET values

>>> s = "http://vimeo.com/1496152?test=test"
>>> markdown.markdown(s, ['video'])
u'<p><object data="http://vimeo.com/moogaloop.swf?clip_id=1496152&amp;amp;server=vimeo.com" height="321" type="application/x-shockwave-flash" width="400"><param name="movie" value="http://vimeo.com/moogaloop.swf?clip_id=1496152&amp;amp;server=vimeo.com" /><param name="allowFullScreen" value="true" /></object></p>'

Test Blip.tv

>>> s = "http://blip.tv/file/get/Pycon-PlenarySprintIntro563.flv"
>>> markdown.markdown(s, ['video'])
u'<p><object data="http://blip.tv/scripts/flash/showplayer.swf?file=http://blip.tv/file/get/Pycon-PlenarySprintIntro563.flv" height="300" type="application/x-shockwave-flash" width="480"><param name="movie" value="http://blip.tv/scripts/flash/showplayer.swf?file=http://blip.tv/file/get/Pycon-PlenarySprintIntro563.flv" /><param name="allowFullScreen" value="true" /></object></p>'

"""

import markdown

class VideoExtension(markdown.Extension):
    def __init__(self, configs):
        self.config = {
            'bliptv_width': ['480', 'Width for Blip.tv videos'],
            'bliptv_height': ['300', 'Height for Blip.tv videos'],
            'dailymotion_width': ['480', 'Width for Dailymotion videos'],
            'dailymotion_height': ['405', 'Height for Dailymotion videos'],
            'metacafe_width': ['498', 'Width for Metacafe videos'],
            'metacafe_height': ['423', 'Height for Metacafe videos'],
            'veoh_width': ['410', 'Width for Veoh videos'],
            'veoh_height': ['341', 'Height for Veoh videos'],
            'vimeo_width': ['400', 'Width for Vimeo videos'],
            'vimeo_height': ['321', 'Height for Vimeo videos'],
            'yahoo_width': ['512', 'Width for Yahoo! videos'],
            'yahoo_height': ['322', 'Height for Yahoo! videos'],
            'youtube_width': ['425', 'Width for Youtube videos'],
            'youtube_height': ['344', 'Height for Youtube videos'],
        }

        # Override defaults with user settings
        for key, value in configs:
            self.setConfig(key, value)

    def extendMarkdown(self, md, md_globals):
        BLIPTV_RE = r'([^(]|^)http://(\w+\.|)blip.tv/file/get/(?P<bliptvfile>\S+.flv)'
        BLIPTV_PATTERN = Bliptv(BLIPTV_RE)
        BLIPTV_PATTERN.md = md
        BLIPTV_PATTERN.ext = self
        md.inlinePatterns.add('bliptv', BLIPTV_PATTERN, "<reference")

        DAILYMOTION_RE = r'([^(]|^)http://www\.dailymotion\.com/(?P<dailymotionid>\S+)'
        DAILYMOTION_PATTERN = Dailymotion(DAILYMOTION_RE)
        DAILYMOTION_PATTERN.md = md
        DAILYMOTION_PATTERN.ext = self
        md.inlinePatterns.add('dailymotion', DAILYMOTION_PATTERN, "<reference")

        METACAFE_RE = r'([^(]|^)http://www\.metacafe\.com/watch/(?P<metacafeid>\S+)/'
        METACAFE_PATTERN = Metacafe(METACAFE_RE)
        METACAFE_PATTERN.md = md
        METACAFE_PATTERN.ext = self
        md.inlinePatterns.add('metacafe', METACAFE_PATTERN, "<reference")

        VEOH_RE = r'([^(]|^)http://www\.veoh\.com/\S*(#watch%3D|watch/)(?P<veohid>\w+)'
        VEOH_PATTERN = Veoh(VEOH_RE)
        VEOH_PATTERN.md = md
        VEOH_PATTERN.ext = self
        md.inlinePatterns.add('veoh', VEOH_PATTERN, "<reference")

        VIMEO_RE = r'([^(]|^)http://(www.|)vimeo\.com/(?P<vimeoid>\d+)\S*'
        VIMEO_PATTERN = Vimeo(VIMEO_RE)
        VIMEO_PATTERN.md = md
        VIMEO_PATTERN.ext = self
        md.inlinePatterns.add('vimeo', VIMEO_PATTERN, "<reference")

        YAHOO_RE = r'([^(]|^)http://video\.yahoo\.com/watch/(?P<yahoovid>\d+)/(?P<yahooid>\d+)'
        YAHOO_PATTERN = Yahoo(YAHOO_RE)
        YAHOO_PATTERN.md = md
        YAHOO_PATTERN.ext = self
        md.inlinePatterns.add('yahoo', YAHOO_PATTERN, "<reference")

        YOUTUBE_RE = r'([^(]|^)http://www\.youtube\.com/watch\?\S*v=(?P<youtubeid>[A-Za-z0-9_-]+)\S*'
        YOUTUBE_PATTERN = Youtube(YOUTUBE_RE)
        YOUTUBE_PATTERN.md = md
        YOUTUBE_PATTERN.ext = self
        md.inlinePatterns.add('youtube', YOUTUBE_PATTERN, "<reference")

class Bliptv(markdown.inlinepatterns.Pattern):
    def handleMatch(self, m):
        url = 'http://blip.tv/scripts/flash/showplayer.swf?file=http://blip.tv/file/get/%s' % m.group('bliptvfile')
        width = self.ext.config['bliptv_width'][0]
        height = self.ext.config['bliptv_height'][0]
        return flash_object(url, width, height)

class Dailymotion(markdown.inlinepatterns.Pattern):
    def handleMatch(self, m):
        url = 'http://www.dailymotion.com/swf/%s' % m.group('dailymotionid').split('/')[-1]
        width = self.ext.config['dailymotion_width'][0]
        height = self.ext.config['dailymotion_height'][0]
        return flash_object(url, width, height)

class Metacafe(markdown.inlinepatterns.Pattern):
    def handleMatch(self, m):
        url = 'http://www.metacafe.com/fplayer/%s.swf' % m.group('metacafeid')
        width = self.ext.config['metacafe_width'][0]
        height = self.ext.config['metacafe_height'][0]
        return flash_object(url, width, height)

class Veoh(markdown.inlinepatterns.Pattern):
    def handleMatch(self, m):
        url = 'http://www.veoh.com/videodetails2.swf?permalinkId=%s' % m.group('veohid')
        width = self.ext.config['veoh_width'][0]
        height = self.ext.config['veoh_height'][0]
        return flash_object(url, width, height)

class Vimeo(markdown.inlinepatterns.Pattern):
    def handleMatch(self, m):
        url = 'http://vimeo.com/moogaloop.swf?clip_id=%s&amp;server=vimeo.com' % m.group('vimeoid')
        width = self.ext.config['vimeo_width'][0]
        height = self.ext.config['vimeo_height'][0]
        return flash_object(url, width, height)

class Yahoo(markdown.inlinepatterns.Pattern):
    def handleMatch(self, m):
        url = "http://d.yimg.com/static.video.yahoo.com/yep/YV_YEP.swf?ver=2.2.40"
        width = self.ext.config['yahoo_width'][0]
        height = self.ext.config['yahoo_height'][0]
        obj = flash_object(url, width, height)
        param = markdown.etree.Element('param')
        param.set('name', 'flashVars')
        param.set('value', "id=%s&vid=%s" % (m.group('yahooid'),
                m.group('yahoovid')))
        obj.append(param)
        return obj

class Youtube(markdown.inlinepatterns.Pattern):
    def handleMatch(self, m):
        url = 'http://www.youtube.com/v/%s' % m.group('youtubeid')
        width = self.ext.config['youtube_width'][0]
        height = self.ext.config['youtube_height'][0]
        return flash_object(url, width, height)

def flash_object(url, width, height):
        obj = markdown.etree.Element('object')
        obj.set('type', 'application/x-shockwave-flash')
        obj.set('width', width)
        obj.set('height', height)
        obj.set('data', url)
        param = markdown.etree.Element('param')
        param.set('name', 'movie')
        param.set('value', url)
        obj.append(param)
        param = markdown.etree.Element('param')
        param.set('name', 'allowFullScreen')
        param.set('value', 'true')
        obj.append(param)
        return obj

def makeExtension(configs=None) :
    return VideoExtension(configs=configs)

if __name__ == "__main__":
    import doctest
    doctest.testmod()