Skip to content

Instantly share code, notes, and snippets.

@SpotlightKid
Created April 27, 2016 16:38
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save SpotlightKid/94b3e9c7cfac467ff920d09efe601e0e to your computer and use it in GitHub Desktop.
Save SpotlightKid/94b3e9c7cfac467ff920d09efe601e0e to your computer and use it in GitHub Desktop.
Nikola plugin for embedding content from popular sites with micawber and Noembed
[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
# -*- 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