mirror of
https://github.com/Hopiu/python-markdown-oembed.git
synced 2026-03-16 22:10:24 +00:00
initial commit
Functional beta
This commit is contained in:
commit
e4ec8a72fb
9 changed files with 234 additions and 0 deletions
4
.gitignore
vendored
Normal file
4
.gitignore
vendored
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
.DS_Store
|
||||
.idea
|
||||
*.pyc
|
||||
*.egg-info
|
||||
9
README.markdown
Normal file
9
README.markdown
Normal 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
6
mdx_oembed/__init__.py
Normal 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
16
mdx_oembed/endpoints.py
Normal 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
22
mdx_oembed/extension.py
Normal 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
|
||||
23
mdx_oembed/inlinepatterns.py
Normal file
23
mdx_oembed/inlinepatterns.py
Normal 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
0
mdx_oembed/version.py
Normal file
40
setup.py
Normal file
40
setup.py
Normal 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
114
tests.py
Normal 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 = ''
|
||||
match = self.re.match(text)
|
||||
self.assertIsNone(match)
|
||||
|
||||
def test_ignore_absolute_image_link(self):
|
||||
text = ''
|
||||
match = self.re.match(text)
|
||||
self.assertIsNone(match)
|
||||
|
||||
def test_ignore_png_image_link(self):
|
||||
text = ''
|
||||
match = self.re.match(text)
|
||||
self.assertIsNone(match)
|
||||
|
||||
def test_ignore_jpg_image_link(self):
|
||||
text = ''
|
||||
match = self.re.match(text)
|
||||
self.assertIsNone(match)
|
||||
|
||||
def test_ignore_gif_image_link(self):
|
||||
text = ''
|
||||
match = self.re.match(text)
|
||||
self.assertIsNone(match)
|
||||
|
||||
def test_find_youtube_link(self):
|
||||
text = ''
|
||||
match = self.re.match(text)
|
||||
self.assertIsNotNone(match)
|
||||
|
||||
def test_find_youtube_short_link(self):
|
||||
text = ''
|
||||
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 = ''
|
||||
expected = '<p><img alt="alt" src="image.png" /></p>'
|
||||
output = self.markdown.convert(text)
|
||||
self.assertEqual(output, expected)
|
||||
|
||||
def test_slash_relative(self):
|
||||
text = ''
|
||||
expected = '<p><img alt="alt" src="/image.png" /></p>'
|
||||
output = self.markdown.convert(text)
|
||||
self.assertEqual(output, expected)
|
||||
|
||||
def test_absolute(self):
|
||||
text = ''
|
||||
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 = ''
|
||||
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 = ''
|
||||
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 = ''
|
||||
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)
|
||||
|
||||
Loading…
Reference in a new issue