diff options
Diffstat (limited to 'nikola/plugins/compile_rest')
| -rw-r--r-- | nikola/plugins/compile_rest/__init__.py | 36 | ||||
| -rw-r--r-- | nikola/plugins/compile_rest/gist_directive.py | 56 | ||||
| -rw-r--r-- | nikola/plugins/compile_rest/pygments_code_block_directive.py | 32 | ||||
| -rw-r--r-- | nikola/plugins/compile_rest/slides.py | 26 | ||||
| -rw-r--r-- | nikola/plugins/compile_rest/vimeo.py | 92 | ||||
| -rw-r--r-- | nikola/plugins/compile_rest/youtube.py | 11 |
6 files changed, 209 insertions, 44 deletions
diff --git a/nikola/plugins/compile_rest/__init__.py b/nikola/plugins/compile_rest/__init__.py index 0e677e1..4191add 100644 --- a/nikola/plugins/compile_rest/__init__.py +++ b/nikola/plugins/compile_rest/__init__.py @@ -8,11 +8,11 @@ # distribute, sublicense, and/or sell copies of the # Software, and to permit persons to whom the Software is # furnished to do so, subject to the following conditions: -# +# # The above copyright notice and this permission notice # shall be included in all copies or substantial portions of # the Software. -# +# # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY # KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE # WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR @@ -38,8 +38,12 @@ directives.register_directive('listing', listings_directive) from .youtube import youtube directives.register_directive('youtube', youtube) +from .vimeo import vimeo +directives.register_directive('vimeo', vimeo) from .slides import slides directives.register_directive('slides', slides) +from .gist_directive import GitHubGist +directives.register_directive('gist', GitHubGist) from nikola.plugin_categories import PageCompiler @@ -59,23 +63,33 @@ class CompileRest(PageCompiler): with codecs.open(dest, "w+", "utf8") as out_file: with codecs.open(source, "r", "utf8") as in_file: data = in_file.read() - output, error_level = rst2html(data, - settings_overrides={'initial_header_level': 2}) + output, error_level = rst2html( + data, settings_overrides={'initial_header_level': 2}) out_file.write(output) if error_level < 3: return True else: return False + def create_post(self, path, onefile=False, title="", slug="", date="", + tags=""): + with codecs.open(path, "wb+", "utf8") as fd: + if onefile: + fd.write('.. title: %s\n' % title) + fd.write('.. slug: %s\n' % slug) + fd.write('.. date: %s\n' % date) + fd.write('.. tags: %s\n' % tags) + fd.write('.. link: \n') + fd.write('.. description: \n\n') + fd.write("\nWrite your post here.") + def rst2html(source, source_path=None, source_class=docutils.io.StringInput, - destination_path=None, - reader=None, reader_name='standalone', - parser=None, parser_name='restructuredtext', - writer=None, writer_name='html', - settings=None, settings_spec=None, - settings_overrides=None, config_section=None, - enable_exit_status=None): + destination_path=None, reader=None, reader_name='standalone', + parser=None, parser_name='restructuredtext', writer=None, + writer_name='html', settings=None, settings_spec=None, + settings_overrides=None, config_section=None, + enable_exit_status=None): """ Set up & run a `Publisher`, and return a dictionary of document parts. Dictionary keys are the names of parts, and values are Unicode strings; diff --git a/nikola/plugins/compile_rest/gist_directive.py b/nikola/plugins/compile_rest/gist_directive.py new file mode 100644 index 0000000..3bfe818 --- /dev/null +++ b/nikola/plugins/compile_rest/gist_directive.py @@ -0,0 +1,56 @@ +# This file is public domain according to its author, Brian Hsu + +from docutils.parsers.rst import Directive, directives +from docutils import nodes + +try: + import requests +except ImportError: + requests = None # NOQA + + +class GitHubGist(Directive): + """ Embed GitHub Gist. + + Usage: + .. gist:: GIST_ID + + """ + + required_arguments = 1 + optional_arguments = 1 + option_spec = {'file': directives.unchanged} + final_argument_whitespace = True + has_content = False + + def get_raw_gist_with_filename(self, gistID, filename): + url = "https://raw.github.com/gist/%s/%s" % (gistID, filename) + return requests.get(url).text + + def get_raw_gist(self, gistID): + url = "https://raw.github.com/gist/%s/" % (gistID) + return requests.get(url).text + + def run(self): + if requests is None: + print('To use the gist directive, you need to install the ' + '"requests" package.') + return [] + gistID = self.arguments[0].strip() + embedHTML = "" + rawGist = "" + + if 'file' in self.options: + filename = self.options['file'] + rawGist = (self.get_raw_gist_with_filename(gistID, filename)) + embedHTML = ('<script src="https://gist.github.com/%s.js?file=%s">' + '</script>') % (gistID, filename) + else: + rawGist = (self.get_raw_gist(gistID)) + embedHTML = ('<script src="https://gist.github.com/%s.js">' + '</script>') % gistID + + return [nodes.raw('', embedHTML, format='html'), + nodes.raw('', '<noscript>', format='html'), + nodes.literal_block('', rawGist), + nodes.raw('', '</noscript>', format='html')] diff --git a/nikola/plugins/compile_rest/pygments_code_block_directive.py b/nikola/plugins/compile_rest/pygments_code_block_directive.py index a83098f..f858427 100644 --- a/nikola/plugins/compile_rest/pygments_code_block_directive.py +++ b/nikola/plugins/compile_rest/pygments_code_block_directive.py @@ -36,9 +36,9 @@ import codecs from copy import copy
import os
try:
- from urlparse import urlparse, urlunsplit
+ from urlparse import urlunsplit
except ImportError:
- from urllib.parse import urlparse, urlunsplit
+ from urllib.parse import urlunsplit # NOQA
from docutils import nodes, core
from docutils.parsers.rst import directives
@@ -96,8 +96,7 @@ class DocutilsInterface(object): try:
if self.language and str(self.language).lower() != 'none':
lexer = get_lexer_by_name(self.language.lower(),
- **self.custom_args
- )
+ **self.custom_args)
else:
lexer = get_lexer_by_name('text', **self.custom_args)
except ValueError:
@@ -136,7 +135,7 @@ class DocutilsInterface(object): # ::
def code_block_directive(name, arguments, options, content, lineno,
- content_offset, block_text, state, state_machine):
+ content_offset, block_text, state, state_machine):
"""Parse and classify content of a code_block."""
if 'include' in options:
try:
@@ -173,8 +172,8 @@ def code_block_directive(name, arguments, options, content, lineno, # Move the after_index to the beginning of the line with the
# match.
for char in content[after_index:0:-1]:
- # codecs always opens binary. This works with '\n',
- # '\r' and '\r\n'. We are going backwards, so
+ # codecs always opens binary. This works with '\n',
+ # '\r' and '\r\n'. We are going backwards, so
# '\n' is found first in '\r\n'.
# Going with .splitlines() seems more appropriate
# but needs a few more changes.
@@ -197,7 +196,7 @@ def code_block_directive(name, arguments, options, content, lineno, 'code-block directive:\nText not found.' %
options['start-after'])
line_offset = len(content[:after_index +
- len(after_text)].splitlines())
+ len(after_text)].splitlines())
content = content[after_index + len(after_text):]
# same changes here for the same reason
@@ -249,7 +248,7 @@ def code_block_directive(name, arguments, options, content, lineno, lnwidth = len(str(total_lines))
fstr = "\n%%%dd " % lnwidth
code_block += nodes.inline(fstr[1:] % lineno, fstr[1:] % lineno,
- classes=['linenumber'])
+ classes=['linenumber'])
# parse content with pygments and add to code_block element
content = content.rstrip()
@@ -260,6 +259,9 @@ def code_block_directive(name, arguments, options, content, lineno, l = list(DocutilsInterface(content, language, options))
if l[-1] == ('', '\n'):
l = l[:-1]
+ # We strip last element for the same reason (trailing \n looks bad)
+ if l:
+ l[-1] = (l[-1][0], l[-1][1].rstrip())
for cls, value in l:
if withln and "\n" in value:
# Split on the "\n"s
@@ -271,7 +273,7 @@ def code_block_directive(name, arguments, options, content, lineno, for chunk, ln in zip(values, linenos)[1:]:
if ln <= total_lines:
code_block += nodes.inline(fstr % ln, fstr % ln,
- classes=['linenumber'])
+ classes=['linenumber'])
code_block += nodes.Text(chunk, chunk)
lineno += len(values) - 1
@@ -317,8 +319,8 @@ def string_bool(argument): elif argument.lower() == 'false':
return False
else:
- raise ValueError('"%s" unknown; choose from "True" or "False"'
- % argument)
+ raise ValueError('"%s" unknown; choose from "True" or "False"' %
+ argument)
def csharp_unicodelevel(argument):
@@ -339,9 +341,9 @@ def listings_directive(name, arguments, options, content, lineno, options['include'] = os.path.join('listings', fname)
target = urlunsplit(("link", 'listing', fname, '', ''))
generated_nodes = [core.publish_doctree('`%s <%s>`_' % (fname, target))[0]]
- generated_nodes += code_block_directive(name, [arguments[1]],
- options, content, lineno, content_offset, block_text,
- state, state_machine)
+ generated_nodes += code_block_directive(name, [arguments[1]], options,
+ content, lineno, content_offset,
+ block_text, state, state_machine)
return generated_nodes
code_block_directive.arguments = (1, 0, 1)
diff --git a/nikola/plugins/compile_rest/slides.py b/nikola/plugins/compile_rest/slides.py index 942a7d4..c9d55f3 100644 --- a/nikola/plugins/compile_rest/slides.py +++ b/nikola/plugins/compile_rest/slides.py @@ -8,11 +8,11 @@ # distribute, sublicense, and/or sell copies of the # Software, and to permit persons to whom the Software is # furnished to do so, subject to the following conditions: -# +# # The above copyright notice and this permission notice # shall be included in all copies or substantial portions of # the Software. -# +# # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY # KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE # WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR @@ -27,10 +27,9 @@ import json from docutils import nodes from docutils.parsers.rst import Directive, directives -class slides(Directive): +class slides(Directive): """ Restructured text extension for inserting slideshows.""" - has_content = True option_spec = { "preload": directives.flag, @@ -60,12 +59,13 @@ class slides(Directive): "animationStart": directives.unchanged, "animationComplete": directives.unchanged, } - + def run(self): if len(self.content) == 0: return - for opt in ("preload", "generateNextPrev", "pagination", "generatePagination", - "crossfade", "randomize", "hoverPause", "autoHeight", "bigTarget"): + for opt in ("preload", "generateNextPrev", "pagination", + "generatePagination", "crossfade", "randomize", + "hoverPause", "autoHeight", "bigTarget"): if opt in self.options: self.options[opt] = True options = { @@ -73,17 +73,19 @@ class slides(Directive): "bigTarget": True, "paginationClass": "pager", "currentClass": "slide-current" - } + } options.update(self.options) options = json.dumps(options) output = [] - output.append("""<script> $(function(){ $("#slides").slides(%s); }); </script>""" % options) - output.append("""<div id="slides" class="slides"><div class="slides_container">""") + output.append('<script> $(function(){ $("#slides").slides(%s); });' + '</script>' % options) + output.append('<div id="slides" class="slides"><div ' + 'class="slides_container">') for image in self.content: output.append("""<div><img src="%s"></div>""" % image) output.append("""</div></div>""") - + return [nodes.raw('', '\n'.join(output), format='html')] - + directives.register_directive('slides', slides) diff --git a/nikola/plugins/compile_rest/vimeo.py b/nikola/plugins/compile_rest/vimeo.py new file mode 100644 index 0000000..3eefcc4 --- /dev/null +++ b/nikola/plugins/compile_rest/vimeo.py @@ -0,0 +1,92 @@ +# Copyright (c) 2012 Roberto Alsina y otros. + +# Permission is hereby granted, free of charge, to any +# person obtaining a copy of this software and associated +# documentation files (the "Software"), to deal in the +# Software without restriction, including without limitation +# the rights to use, copy, modify, merge, publish, +# distribute, sublicense, and/or sell copies of the +# Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice +# shall be included in all copies or substantial portions of +# the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY +# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE +# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +# PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS +# OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR +# OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +# OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +# SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +from docutils import nodes +from docutils.parsers.rst import directives + +try: + import requests +except ImportError: + requests = None # NOQA +try: + import json # python 2.6 or higher +except ImportError: + try: + import simplejson as json # NOQA + except ImportError: + json = None + +CODE = """<iframe src="http://player.vimeo.com/video/%(vimeo_id)s" +width="%(width)s" height="%(height)s" +frameborder="0" webkitAllowFullScreen mozallowfullscreen allowFullScreen> +</iframe> +""" + +VIDEO_DEFAULT_HEIGHT = 500 +VIDEO_DEFAULT_WIDTH = 281 + + +def vimeo(name, args, options, content, lineno, contentOffset, blockText, + state, stateMachine): + """ Restructured text extension for inserting vimeo embedded videos """ + if requests is None: + raise Exception("To use the Vimeo directive you need to install the " + "requests module.") + if json is None: + raise Exception("To use the Vimeo directive you need python 2.6 or to " + "install the simplejson module.") + if len(content) == 0: + return + + string_vars = {'vimeo_id': content[0]} + extra_args = content[1:] # Because content[0] is ID + extra_args = [ea.strip().split("=") for ea in extra_args] # key=value + extra_args = [ea for ea in extra_args if len(ea) == 2] # drop bad lines + extra_args = dict(extra_args) + if 'width' in extra_args: + string_vars['width'] = extra_args.pop('width') + if 'height' in extra_args: + string_vars['height'] = extra_args.pop('height') + + # Only need to make a connection if width and height aren't provided + if 'height' not in string_vars or 'width' not in string_vars: + string_vars['height'] = VIDEO_DEFAULT_HEIGHT + string_vars['width'] = VIDEO_DEFAULT_WIDTH + + if json: # we can attempt to retrieve video attributes from vimeo + try: + url = ('http://vimeo.com/api/v2/video/%(vimeo_id)s.json' % + string_vars) + data = requests.get(url).text + video_attributes = json.loads(data) + string_vars['height'] = video_attributes['height'] + string_vars['width'] = video_attributes['width'] + except Exception: + # fall back to the defaults + pass + + return [nodes.raw('', CODE % string_vars, format='html')] + +vimeo.content = True +directives.register_directive('vimeo', vimeo) diff --git a/nikola/plugins/compile_rest/youtube.py b/nikola/plugins/compile_rest/youtube.py index 0765158..fe3b28b 100644 --- a/nikola/plugins/compile_rest/youtube.py +++ b/nikola/plugins/compile_rest/youtube.py @@ -8,11 +8,11 @@ # distribute, sublicense, and/or sell copies of the # Software, and to permit persons to whom the Software is # furnished to do so, subject to the following conditions: -# +# # The above copyright notice and this permission notice # shall be included in all copies or substantial portions of # the Software. -# +# # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY # KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE # WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR @@ -28,9 +28,8 @@ from docutils.parsers.rst import directives CODE = """\ <iframe width="%(width)s" height="%(height)s" -src="http://www.youtube.com/embed/%(yid)s?rel=0&hd=1&wmode=transparent"> -</iframe> -""" +src="http://www.youtube.com/embed/%(yid)s?rel=0&hd=1&wmode=transparent" +></iframe>""" def youtube(name, args, options, content, lineno, @@ -43,7 +42,7 @@ def youtube(name, args, options, content, lineno, 'width': 425, 'height': 344, 'extra': '' - } + } extra_args = content[1:] # Because content[0] is ID extra_args = [ea.strip().split("=") for ea in extra_args] # key=value extra_args = [ea for ea in extra_args if len(ea) == 2] # drop bad lines |
