Created
April 27, 2016 16:38
-
-
Save SpotlightKid/94b3e9c7cfac467ff920d09efe601e0e to your computer and use it in GitHub Desktop.
Nikola plugin for embedding content from popular sites with micawber and Noembed
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
[Core] | |
name = rest_noembed | |
module = noembed | |
[Nikola] | |
compiler = rest | |
plugincategory = CompilerExtension | |
[Documentation] | |
author = Christopher Arndt | |
version = 0.1 | |
website = https://github.com/SpotlightKid/nikola-plugin-noembed | |
description = Directive to support oembed via micawber using NoEmbed provider |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# -*- coding: utf-8 -*- | |
"""Nikola plugin for embedding content from popular sites with micawber_ and | |
Noembed_. | |
Provides a ReST directive and a generic Nikola shortcode. | |
ReST directive usage example:: | |
.. noembed:: http://soundcloud.com/myuser/my-track | |
Shortcode usage example:: | |
{{% noembed http://soundcloud.com/myuser/my-track %}} | |
.. _micawber: https://github.com/coleifer/micawber/ | |
.. _noembed: http://www.noembed.com/ | |
When you use this directive / shortcode in a post or story and generate the | |
output, the plugin will download the list of OEmbed Providers from noembed.com | |
and then use the provider matching the URL you specified to download the HTML | |
snippet to include in your post / story to embed the content the URL is | |
pointing to. Both the list of providers and the embedding HTML code are cashed | |
locally in files below your site's cache directory. So when you re-generate | |
your site and you haven't changed or added any noembed directives / shortcodes, | |
no internet connection is needed for the plugin. You can safely delete the | |
cache files by running `nikola clean`. | |
""" | |
import shelve | |
from os.path import join | |
from docutils import nodes | |
from docutils.parsers.rst import Directive, directives | |
try: | |
import micawber | |
except ImportError: | |
micawber = None # NOQA | |
from nikola.plugin_categories import RestExtension | |
from nikola.utils import req_missing | |
class Plugin(RestExtension): | |
"""Plugin for noembed reST directive and generic Nikola shortcode.""" | |
name = "rest_noembed" | |
def set_site(self, site): | |
"""Set Nikola site.""" | |
self.site = site | |
directives.register_directive('noembed', Noembed(plugin=self)) | |
self.site.register_shortcode('noembed', self.gen_noembed) | |
self.cachefn = join(site.config['CACHE_FOLDER'], "noembed.cache") | |
return super(Plugin, self).set_site(site) | |
def get_providers(self): | |
try: | |
with shelve.open(self.cachefn) as cache: | |
providers = cache['_providers'] | |
except (OSError, IOError, KeyError): | |
providers = micawber.bootstrap_noembed() | |
with shelve.open(self.cachefn, 'w') as cache: | |
cache['_providers'] = providers | |
return providers | |
def gen_noembed(self, url, *args, **kw): | |
try: | |
with shelve.open(self.cachefn) as cache: | |
text = cache[url] | |
except (OSError, IOError, KeyError): | |
if micawber is None: | |
msg = req_missing(['micawber'], 'use the noembed directive', | |
optional=True) | |
text = '<div class="text-error">{0}</div>'.format(msg) | |
else: | |
text = micawber.parse_text(url, self.get_providers()) | |
with shelve.open(self.cachefn, 'w') as cache: | |
cache[url] = text | |
return text | |
class Noembed(Directive): | |
"""ReST extension for embedding content from popular sites using micawber | |
and Noembed.""" | |
has_content = False | |
required_arguments = 1 | |
optional_arguments = 999 | |
def __init__(self, *args, **kw): | |
self.plugin = kw.pop('plugin', None) | |
# XXX: ugly hack to be able to receive state: | |
# instead of a class object, we pass an instance of Noembed to | |
# docutils' register_directive, which already has some dynamic state | |
# set (the 'plugin' attribute referencing our plugin instance). | |
# When docutils calls the instance (normally it would instantiate the | |
# class) the '__call__' method is called and the delayed | |
# initialization of the superclass is carried out. | |
def __call__(self, *args, **kw): | |
super().__init__(*args, **kw) | |
return self | |
def run(self): | |
"""Run noembed directive.""" | |
html = self.plugin.gen_noembed(" ".join(self.arguments)) | |
return [nodes.raw('', html, format='html')] |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment