From e4ec8a72fbf7d066d1a7ad803fd94a4a4cd27e3b Mon Sep 17 00:00:00 2001 From: "J. Tanner Netterville" Date: Tue, 13 Nov 2012 15:28:10 -0600 Subject: [PATCH] initial commit Functional beta --- .gitignore | 4 ++ README.markdown | 9 +++ mdx_oembed/__init__.py | 6 ++ mdx_oembed/endpoints.py | 16 +++++ mdx_oembed/extension.py | 22 +++++++ mdx_oembed/inlinepatterns.py | 23 +++++++ mdx_oembed/version.py | 0 setup.py | 40 ++++++++++++ tests.py | 114 +++++++++++++++++++++++++++++++++++ 9 files changed, 234 insertions(+) create mode 100644 .gitignore create mode 100644 README.markdown create mode 100644 mdx_oembed/__init__.py create mode 100644 mdx_oembed/endpoints.py create mode 100644 mdx_oembed/extension.py create mode 100644 mdx_oembed/inlinepatterns.py create mode 100644 mdx_oembed/version.py create mode 100644 setup.py create mode 100644 tests.py diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..d2a4fe6 --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +.DS_Store +.idea +*.pyc +*.egg-info diff --git a/README.markdown b/README.markdown new file mode 100644 index 0000000..34d9dbe --- /dev/null +++ b/README.markdown @@ -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) diff --git a/mdx_oembed/__init__.py b/mdx_oembed/__init__.py new file mode 100644 index 0000000..4395f4b --- /dev/null +++ b/mdx_oembed/__init__.py @@ -0,0 +1,6 @@ +# -*- coding: utf-8 -*- +from mdx_oembed.extension import OEmbedExtension + + +def makeExtension(configs=None): + return OEmbedExtension(configs=configs) diff --git a/mdx_oembed/endpoints.py b/mdx_oembed/endpoints.py new file mode 100644 index 0000000..35d5223 --- /dev/null +++ b/mdx_oembed/endpoints.py @@ -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/*', + ]), +} diff --git a/mdx_oembed/extension.py b/mdx_oembed/extension.py new file mode 100644 index 0000000..8c7a86d --- /dev/null +++ b/mdx_oembed/extension.py @@ -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, '= 0.2.1", + "Markdown >= 2.2.0", + ], + + test_suite='nose.collector', + tests_require=['WebTest >= 1.2', 'BeautifulSoup', 'pytidylib', 'poster'] +) diff --git a/tests.py b/tests.py new file mode 100644 index 0000000..41a8e72 --- /dev/null +++ b/tests.py @@ -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 = '

alt

' + output = self.markdown.convert(text) + self.assertEqual(output, expected) + + def test_slash_relative(self): + text = '![alt](/image.png)' + expected = '

alt

' + output = self.markdown.convert(text) + self.assertEqual(output, expected) + + def test_absolute(self): + text = '![Mumbo Jumbo](http://tannern.com/mumbo-jumbo.jpg)' + expected = '

Mumbo Jumbo

' + 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 = '' + 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 = '' + output = self.markdown.convert(text) + self.assertEqual(output, expected) + + def test_vimeio_link(self): + """ + Vimeo video link. + """ + text = '![link](http://vimeo.com/52970271)' + expected = '' + output = self.markdown.convert(text) + self.assertEqual(output, expected) +