initial commit

Functional beta
This commit is contained in:
J. Tanner Netterville 2012-11-13 15:28:10 -06:00
commit e4ec8a72fb
9 changed files with 234 additions and 0 deletions

4
.gitignore vendored Normal file
View file

@ -0,0 +1,4 @@
.DS_Store
.idea
*.pyc
*.egg-info

9
README.markdown Normal file
View file

@ -0,0 +1,9 @@
# Python Markdown oEmbed
Markdown extension to allow media embedding using the oEmbed standard.
# Links
- [Markdown](http://daringfireball.net/projects/markdown/)
- [oEmbed](http://www.oembed.com/)
- [python-oembed](https://github.com/abarmat/python-oembed)

6
mdx_oembed/__init__.py Normal file
View file

@ -0,0 +1,6 @@
# -*- coding: utf-8 -*-
from mdx_oembed.extension import OEmbedExtension
def makeExtension(configs=None):
return OEmbedExtension(configs=configs)

16
mdx_oembed/endpoints.py Normal file
View file

@ -0,0 +1,16 @@
# -*- coding: utf-8 -*-
import oembed
ENDPOINTS = {
'youtube': oembed.OEmbedEndpoint('http://www.youtube.com/oembed', [
'http://(*.)?youtube.com/*',
'http://youtu.be/*',
]),
'flickr': oembed.OEmbedEndpoint('http://www.flickr.com/services/oembed/', [
'http://*.flickr.com/*',
]),
'vimeo': oembed.OEmbedEndpoint('http://vimeo.com/api/oembed.json', [
'http://vimeo.com/*',
]),
}

22
mdx_oembed/extension.py Normal file
View file

@ -0,0 +1,22 @@
# -*- coding: utf-8 -*-
from markdown import Extension
import oembed
from mdx_oembed.endpoints import ENDPOINTS
from mdx_oembed.inlinepatterns import OEmbedLinkPattern, OEMBED_LINK_RE
class OEmbedExtension(Extension):
def extendMarkdown(self, md, md_globals):
self.oembed_consumer = self.prepare_oembed_consumer()
pattern = OEmbedLinkPattern(OEMBED_LINK_RE, md, self.oembed_consumer)
md.inlinePatterns.add('oembed_link', pattern, '<image_link')
def prepare_oembed_consumer(self):
allowed_endpoints = self.getConfig('allowed_endpoints',
ENDPOINTS.keys())
consumer = oembed.OEmbedConsumer()
[consumer.addEndpoint(v)
for k,v in ENDPOINTS.items()
if k in allowed_endpoints]
return consumer

View file

@ -0,0 +1,23 @@
# -*- coding: utf-8 -*-
import logging
from markdown.inlinepatterns import Pattern
LOG = logging.getLogger(__name__)
OEMBED_LINK_RE = r'\!\[([^\]]*)\]\((https?://[^\)]*)' \
r'(?<!png)(?<!jpg)(?<!jpeg)(?<!gif)\)'
class OEmbedLinkPattern(Pattern):
def __init__(self, pattern, markdown_instance=None, oembed_consumer=None):
Pattern.__init__(self, pattern, markdown_instance)
self.consumer = oembed_consumer
def handleMatch(self, match):
url = match.group(3).strip()
response = self.consumer.embed(url)
placeholder = self.markdown.htmlStash.store(response['html'])
return placeholder

0
mdx_oembed/version.py Normal file
View file

40
setup.py Normal file
View file

@ -0,0 +1,40 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
try:
from setuptools import setup
except ImportError:
from distutils.core import setup
VERSION = '0.0b'
setup(
name='python-markdown-oembed',
version=VERSION,
description="",
long_description=open('README.markdown').read(),
author='Tanner Netterville',
author_email='tannern@gmail.com',
url='http://tannern.com',
license='MIT',
classifiers=(
"Development Status :: 4 - Beta",
"License :: OSI Approved :: MIT License",
"Programming Language :: Python",
"Programming Language :: Python :: 2.5",
"Programming Language :: Python :: 2.6",
),
keywords='markdown oembed',
packages=[
'mdx_oembed',
],
install_requires=[
"python-oembed >= 0.2.1",
"Markdown >= 2.2.0",
],
test_suite='nose.collector',
tests_require=['WebTest >= 1.2', 'BeautifulSoup', 'pytidylib', 'poster']
)

114
tests.py Normal file
View file

@ -0,0 +1,114 @@
# -*- coding: utf-8 -*-
import re
import unittest
import markdown
from mdx_oembed.extension import OEMBED_LINK_RE
class OEmbedPatternRegexTestCase(unittest.TestCase):
def setUp(self):
self.re = re.compile(OEMBED_LINK_RE)
def test_ignore_relative_image_link(self):
text = '![image](/image.png)'
match = self.re.match(text)
self.assertIsNone(match)
def test_ignore_absolute_image_link(self):
text = '![Mumbo Jumbo](http://tannern.com/mumbo-jumbo.jpg)'
match = self.re.match(text)
self.assertIsNone(match)
def test_ignore_png_image_link(self):
text = '![Mumbo Jumbo](http://tannern.com/mumbo-jumbo.png)'
match = self.re.match(text)
self.assertIsNone(match)
def test_ignore_jpg_image_link(self):
text = '![Mumbo Jumbo](http://tannern.com/mumbo-jumbo.jpg)'
match = self.re.match(text)
self.assertIsNone(match)
def test_ignore_gif_image_link(self):
text = '![Mumbo Jumbo](http://tannern.com/mumbo-jumbo.gif)'
match = self.re.match(text)
self.assertIsNone(match)
def test_find_youtube_link(self):
text = '![video](http://www.youtube.com/watch?v=zqnh_YJBvOI)'
match = self.re.match(text)
self.assertIsNotNone(match)
def test_find_youtube_short_link(self):
text = '![video](http://youtu.be/zqnh_YJBvOI)'
match = self.re.match(text)
self.assertIsNotNone(match)
class OEmbedExtensionTestCase(unittest.TestCase):
def setUp(self):
md_params = {
'extensions': [
'oembed',
],
}
self.markdown = markdown.Markdown(**md_params)
class IgnoredTestCase(OEmbedExtensionTestCase):
"""
The OEmbedExtension should ignore these tags allowing markdown's image
processor to find and handle them.
"""
def test_relative(self):
text = '![alt](image.png)'
expected = '<p><img alt="alt" src="image.png" /></p>'
output = self.markdown.convert(text)
self.assertEqual(output, expected)
def test_slash_relative(self):
text = '![alt](/image.png)'
expected = '<p><img alt="alt" src="/image.png" /></p>'
output = self.markdown.convert(text)
self.assertEqual(output, expected)
def test_absolute(self):
text = '![Mumbo Jumbo](http://tannern.com/mumbo-jumbo.jpg)'
expected = '<p><img alt="Mumbo Jumbo" src="http://tannern.com/mumbo-jumbo.jpg" /></p>'
output = self.markdown.convert(text)
self.assertEqual(output, expected)
class YoutubeTestCase(OEmbedExtensionTestCase):
"""
The OEmbedExtension should handle embedding for these cases.
"""
def test_youtube_link(self):
"""
YouTube video link.
"""
text = '![video](http://www.youtube.com/watch?v=zqnh_YJBvOI)'
expected = '<iframe width="459" height="344" src="http://www.youtube.com/embed/zqnh_YJBvOI?fs=1&feature=oembed" frameborder="0" allowfullscreen></iframe>'
output = self.markdown.convert(text)
self.assertEqual(output, expected)
def test_youtube_short_link(self):
"""
Short format YouTube video link.
"""
text = '![video](http://youtu.be/zqnh_YJBvOI)'
expected = '<iframe width="459" height="344" src="http://www.youtube.com/embed/zqnh_YJBvOI?fs=1&feature=oembed" frameborder="0" allowfullscreen></iframe>'
output = self.markdown.convert(text)
self.assertEqual(output, expected)
def test_vimeio_link(self):
"""
Vimeo video link.
"""
text = '![link](http://vimeo.com/52970271)'
expected = '<iframe src="http://player.vimeo.com/video/52970271" width="1280" height="720" frameborder="0" webkitAllowFullScreen mozallowfullscreen allowFullScreen></iframe>'
output = self.markdown.convert(text)
self.assertEqual(output, expected)