diff options
| author | 2013-05-30 17:41:06 -0300 | |
|---|---|---|
| committer | 2013-05-30 17:41:06 -0300 | |
| commit | 0c4dfdec5b55b6064dccc38bbfb0a7c0699c895a (patch) | |
| tree | a6707225ccc559f7edf50ddd3fdc7fc85145c921 /nikola/plugins/compile_rest | |
| parent | 8b14a1e5b2ca574fdd4fd2377567ec98a110d4b6 (diff) | |
Imported Upstream version 5.4.4
Diffstat (limited to 'nikola/plugins/compile_rest')
| -rw-r--r-- | nikola/plugins/compile_rest/__init__.py | 81 | ||||
| -rw-r--r-- | nikola/plugins/compile_rest/dummy.py | 44 | ||||
| -rw-r--r-- | nikola/plugins/compile_rest/gist_directive.py | 2 | ||||
| -rw-r--r-- | nikola/plugins/compile_rest/listing.py | 121 | ||||
| -rw-r--r-- | nikola/plugins/compile_rest/pygments_code_block_directive.py | 424 | ||||
| -rw-r--r-- | nikola/plugins/compile_rest/slides.py | 79 | ||||
| -rw-r--r-- | nikola/plugins/compile_rest/soundcloud.py | 62 | ||||
| -rw-r--r-- | nikola/plugins/compile_rest/vimeo.py | 114 | ||||
| -rw-r--r-- | nikola/plugins/compile_rest/youtube.py | 57 |
9 files changed, 387 insertions, 597 deletions
diff --git a/nikola/plugins/compile_rest/__init__.py b/nikola/plugins/compile_rest/__init__.py index b0a0c00..3d41571 100644 --- a/nikola/plugins/compile_rest/__init__.py +++ b/nikola/plugins/compile_rest/__init__.py @@ -26,26 +26,28 @@ from __future__ import unicode_literals import codecs import os -import docutils.core -import docutils.io -from docutils.parsers.rst import directives - -from .pygments_code_block_directive import ( - code_block_directive, - listings_directive) -directives.register_directive('code-block', code_block_directive) -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 .soundcloud import soundcloud -directives.register_directive('soundcloud', soundcloud) +try: + import docutils.core + import docutils.io + from docutils.parsers.rst import directives + + from .listing import Listing, CodeBlock + directives.register_directive('code-block', CodeBlock) + directives.register_directive('sourcecode', CodeBlock) + directives.register_directive('listing', Listing) + 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 .soundcloud import SoundCloud + directives.register_directive('soundcloud', SoundCloud) + has_docutils = True +except ImportError: + has_docutils = False from nikola.plugin_categories import PageCompiler @@ -57,6 +59,9 @@ class CompileRest(PageCompiler): def compile_html(self, source, dest): """Compile reSt into HTML.""" + if not has_docutils: + raise Exception('To build this site, you need to install the ' + '"docutils" package.') try: os.makedirs(os.path.dirname(dest)) except: @@ -65,24 +70,38 @@ 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, deps = rst2html( + data, settings_overrides={ + 'initial_header_level': 2, + 'record_dependencies': True, + 'stylesheet_path': None, + 'link_stylesheet': True, + 'syntax_highlight': 'short', + }) out_file.write(output) + deps_path = dest + '.dep' + if deps.list: + with codecs.open(deps_path, "wb+", "utf8") as deps_file: + deps_file.write('\n'.join(deps.list)) + else: + if os.path.isfile(deps_path): + os.unlink(deps_path) if error_level < 3: return True else: return False - def create_post(self, path, onefile=False, title="", slug="", date="", - tags=""): + def create_post(self, path, onefile=False, **kw): + metadata = {} + metadata.update(self.default_metadata) + metadata.update(kw) + d_name = os.path.dirname(path) + if not os.path.isdir(d_name): + os.makedirs(os.path.dirname(path)) with codecs.open(path, "wb+", "utf8") as fd: if onefile: - fd.write('.. title: {0}\n'.format(title)) - fd.write('.. slug: {0}\n'.format(slug)) - fd.write('.. date: {0}\n'.format(date)) - fd.write('.. tags: {0}\n'.format(tags)) - fd.write('.. link: \n') - fd.write('.. description: \n\n') + for k, v in metadata.items(): + fd.write('.. {0}: {1}\n'.format(k, v)) fd.write("\nWrite your post here.") @@ -116,4 +135,4 @@ def rst2html(source, source_path=None, source_class=docutils.io.StringInput, settings_overrides=settings_overrides, config_section=config_section, enable_exit_status=enable_exit_status) - return pub.writer.parts['fragment'], pub.document.reporter.max_level + return pub.writer.parts['fragment'], pub.document.reporter.max_level, pub.settings.record_dependencies diff --git a/nikola/plugins/compile_rest/dummy.py b/nikola/plugins/compile_rest/dummy.py new file mode 100644 index 0000000..39543fd --- /dev/null +++ b/nikola/plugins/compile_rest/dummy.py @@ -0,0 +1,44 @@ +# -*- coding: utf-8 -*- +# 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. + +"""A stupid codeblock replacement for neanderthals and users of Debian Sid.""" + +from __future__ import unicode_literals + +from docutils import nodes +from docutils.parsers.rst import Directive, directives + +CODE = '<pre>{0}</pre>' + + +class CodeBlock(Directive): + required_arguments = 1 + has_content = True + + def run(self): + """ Required by the Directive interface. Create docutils nodes """ + return [nodes.raw('', CODE.format('\n'.join(self.content)), format='html')] + +directives.register_directive('code', CodeBlock) diff --git a/nikola/plugins/compile_rest/gist_directive.py b/nikola/plugins/compile_rest/gist_directive.py index 0ea8f23..1506519 100644 --- a/nikola/plugins/compile_rest/gist_directive.py +++ b/nikola/plugins/compile_rest/gist_directive.py @@ -28,7 +28,7 @@ class GitHubGist(Directive): return requests.get(url).text def get_raw_gist(self, gistID): - url = "https://raw.github.com/gist/{0}/".format(gistID) + url = "https://raw.github.com/gist/{0}".format(gistID) return requests.get(url).text def run(self): diff --git a/nikola/plugins/compile_rest/listing.py b/nikola/plugins/compile_rest/listing.py new file mode 100644 index 0000000..1b816f5 --- /dev/null +++ b/nikola/plugins/compile_rest/listing.py @@ -0,0 +1,121 @@ +# -*- coding: utf-8 -*-
+# 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.
+
+
+""" Define and register a listing directive using the existing CodeBlock """
+
+
+from __future__ import unicode_literals
+from codecs import open as codecs_open # for patching purposes
+try:
+ from urlparse import urlunsplit
+except ImportError:
+ from urllib.parse import urlunsplit # NOQA
+
+from docutils import core
+from docutils.parsers.rst import directives
+try:
+ from docutils.parsers.rst.directives.body import CodeBlock
+except ImportError: # docutils < 0.9 (Debian Sid For The Loss)
+ from dummy import CodeBlock # NOQA
+
+import os
+
+
+class Listing(CodeBlock):
+ """ listing directive: create a CodeBlock from file
+
+ Usage:
+
+ .. listing:: nikola.py python
+ :number-lines:
+
+ """
+ has_content = False
+ required_arguments = 1
+ optional_arguments = 1
+
+ option_spec = {
+ 'start-at': directives.unchanged,
+ 'end-at': directives.unchanged,
+ 'start-after': directives.unchanged,
+ 'end-before': directives.unchanged,
+ }
+
+ def run(self):
+ fname = self.arguments.pop(0)
+ with codecs_open(os.path.join('listings', fname), 'rb+', 'utf8') as fileobject:
+ self.content = fileobject.read().splitlines()
+ self.trim_content()
+ target = urlunsplit(("link", 'listing', fname, '', ''))
+ generated_nodes = (
+ [core.publish_doctree('`{0} <{1}>`_'.format(fname, target))[0]])
+ generated_nodes += self.get_code_from_file(fileobject)
+ return generated_nodes
+
+ def trim_content(self):
+ """Cut the contents based in options."""
+ start = 0
+ end = len(self.content)
+ if 'start-at' in self.options:
+ for start, l in enumerate(self.content):
+ if self.options['start-at'] in l:
+ break
+ else:
+ start = 0
+ elif 'start-before' in self.options:
+ for start, l in enumerate(self.content):
+ if self.options['start-before'] in l:
+ if start > 0:
+ start -= 1
+ break
+ else:
+ start = 0
+ if 'end-at' in self.options:
+ for end, l in enumerate(self.content):
+ if self.options['end-at'] in l:
+ break
+ else:
+ end = len(self.content)
+ elif 'end-before' in self.options:
+ for end, l in enumerate(self.content):
+ if self.options['end-before'] in l:
+ end -= 1
+ break
+ else:
+ end = len(self.content)
+
+ self.content = self.content[start:end]
+
+ def get_code_from_file(self, data):
+ """ Create CodeBlock nodes from file object content """
+ return super(Listing, self).run()
+
+ def assert_has_content(self):
+ """ Listing has no content, override check from superclass """
+ pass
+
+
+directives.register_directive('listing', Listing)
diff --git a/nikola/plugins/compile_rest/pygments_code_block_directive.py b/nikola/plugins/compile_rest/pygments_code_block_directive.py deleted file mode 100644 index 79bada2..0000000 --- a/nikola/plugins/compile_rest/pygments_code_block_directive.py +++ /dev/null @@ -1,424 +0,0 @@ -# -*- coding: utf-8 -*-
-#$Date: 2012-02-28 21:07:21 -0300 (Tue, 28 Feb 2012) $
-#$Revision: 2443 $
-
-# :Author: a Pygments author|contributor; Felix Wiemann; Guenter Milde
-# :Date: $Date: 2012-02-28 21:07:21 -0300 (Tue, 28 Feb 2012) $
-# :Copyright: This module has been placed in the public domain.
-#
-# This is a merge of `Using Pygments in ReST documents`_ from the pygments_
-# documentation, and a `proof of concept`_ by Felix Wiemann.
-#
-# ========== ===========================================================
-# 2007-06-01 Removed redundancy from class values.
-# 2007-06-04 Merge of successive tokens of same type
-# (code taken from pygments.formatters.others).
-# 2007-06-05 Separate docutils formatter script
-# Use pygments' CSS class names (like the html formatter)
-# allowing the use of pygments-produced style sheets.
-# 2007-06-07 Merge in the formatting of the parsed tokens
-# (misnamed as docutils_formatter) as class DocutilsInterface
-# 2007-06-08 Failsave implementation (fallback to a standard literal block
-# if pygments not found)
-# ========== ===========================================================
-#
-# ::
-
-"""Define and register a code-block directive using pygments"""
-
-from __future__ import unicode_literals
-
-# Requirements
-# ------------
-# ::
-
-import codecs
-from copy import copy
-import os
-try:
- from urlparse import urlunsplit
-except ImportError:
- from urllib.parse import urlunsplit # NOQA
-
-from docutils import nodes, core
-from docutils.parsers.rst import directives
-
-pygments = None
-try:
- import pygments
- from pygments.lexers import get_lexer_by_name
- from pygments.formatters.html import _get_ttype_class
-except ImportError:
- pass
-
-
-# Customisation
-# -------------
-#
-# Do not insert inline nodes for the following tokens.
-# (You could add e.g. Token.Punctuation like ``['', 'p']``.) ::
-
-unstyled_tokens = ['']
-
-
-# DocutilsInterface
-# -----------------
-#
-# This interface class combines code from
-# pygments.formatters.html and pygments.formatters.others.
-#
-# It does not require anything of docutils and could also become a part of
-# pygments::
-
-class DocutilsInterface(object):
- """Parse `code` string and yield "classified" tokens.
-
- Arguments
-
- code -- string of source code to parse
- language -- formal language the code is written in.
-
- Merge subsequent tokens of the same token-type.
-
- Yields the tokens as ``(ttype_class, value)`` tuples,
- where ttype_class is taken from pygments.token.STANDARD_TYPES and
- corresponds to the class argument used in pygments html output.
-
- """
-
- def __init__(self, code, language, custom_args={}):
- self.code = code
- self.language = language
- self.custom_args = custom_args
-
- def lex(self):
- """Get lexer for language (use text as fallback)"""
- try:
- if self.language and str(self.language).lower() != 'none':
- lexer = get_lexer_by_name(self.language.lower(),
- **self.custom_args)
- else:
- lexer = get_lexer_by_name('text', **self.custom_args)
- except ValueError:
- # what happens if pygment isn't present ?
- lexer = get_lexer_by_name('text')
- return pygments.lex(self.code, lexer)
-
- def join(self, tokens):
- """join subsequent tokens of same token-type
- """
- tokens = iter(tokens)
- (lasttype, lastval) = next(tokens)
- for ttype, value in tokens:
- if ttype is lasttype:
- lastval += value
- else:
- yield(lasttype, lastval)
- (lasttype, lastval) = (ttype, value)
- yield(lasttype, lastval)
-
- def __iter__(self):
- """parse code string and yield "clasified" tokens
- """
- try:
- tokens = self.lex()
- except IOError:
- yield ('', self.code)
- return
-
- for ttype, value in self.join(tokens):
- yield (_get_ttype_class(ttype), value)
-
-
-# code_block_directive
-# --------------------
-# ::
-
-def code_block_directive(name, arguments, options, content, lineno,
- content_offset, block_text, state, state_machine):
- """Parse and classify content of a code_block."""
- if 'include' in options:
- try:
- if 'encoding' in options:
- encoding = options['encoding']
- else:
- encoding = 'utf-8'
- content = codecs.open(
- options['include'], 'r', encoding).read().rstrip()
- except (IOError, UnicodeError): # no file or problem reading it
- content = ''
- line_offset = 0
- if content:
- # here we define the start-at and end-at options
- # so that limit is included in extraction
- # this is different than the start-after directive of docutils
- # (docutils/parsers/rst/directives/misc.py L73+)
- # which excludes the beginning
- # the reason is we want to be able to define a start-at like
- # def mymethod(self)
- # and have such a definition included
-
- after_text = options.get('start-at', None)
- if after_text:
- # skip content in include_text before
- # *and NOT incl.* a matching text
- after_index = content.find(after_text)
- if after_index < 0:
- raise state_machine.reporter.severe(
- 'Problem with "start-at" option of "{0}" '
- 'code-block directive:\nText not found.'.format(
- options['start-at']))
- # patch mmueller start
- # 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
- # '\n' is found first in '\r\n'.
- # Going with .splitlines() seems more appropriate
- # but needs a few more changes.
- if char == '\n' or char == '\r':
- break
- after_index -= 1
- # patch mmueller end
-
- content = content[after_index:]
- line_offset = len(content[:after_index].splitlines())
-
- after_text = options.get('start-after', None)
- if after_text:
- # skip content in include_text before
- # *and incl.* a matching text
- after_index = content.find(after_text)
- if after_index < 0:
- raise state_machine.reporter.severe(
- 'Problem with "start-after" option of "{0}" '
- 'code-block directive:\nText not found.'.format(
- options['start-after']))
- line_offset = len(content[:after_index +
- len(after_text)].splitlines())
- content = content[after_index + len(after_text):]
-
- # same changes here for the same reason
- before_text = options.get('end-at', None)
- if before_text:
- # skip content in include_text after
- # *and incl.* a matching text
- before_index = content.find(before_text)
- if before_index < 0:
- raise state_machine.reporter.severe(
- 'Problem with "end-at" option of "{0}" '
- 'code-block directive:\nText not found.'.format(
- options['end-at']))
- content = content[:before_index + len(before_text)]
-
- before_text = options.get('end-before', None)
- if before_text:
- # skip content in include_text after
- # *and NOT incl.* a matching text
- before_index = content.find(before_text)
- if before_index < 0:
- raise state_machine.reporter.severe(
- 'Problem with "end-before" option of "{0}" '
- 'code-block directive:\nText not found.'.format(
- options['end-before']))
- content = content[:before_index]
-
- else:
- content = '\n'.join(content)
-
- if 'tabsize' in options:
- tabw = options['tabsize']
- else:
- tabw = int(options.get('tab-width', 8))
-
- content = content.replace('\t', ' ' * tabw)
-
- withln = "linenos" in options
- if not "linenos_offset" in options:
- line_offset = 0
-
- language = arguments[0]
- # create a literal block element and set class argument
- code_block = nodes.literal_block(classes=["code", language])
-
- if withln:
- lineno = 1 + line_offset
- total_lines = content.count('\n') + 1 + line_offset
- lnwidth = len(str(total_lines))
- fstr = "\n%{0}d ".format(lnwidth)
- code_block += nodes.inline(fstr[1:].format(lineno),
- fstr[1:].format(lineno),
- classes=['linenumber'])
-
- # parse content with pygments and add to code_block element
- content = content.rstrip()
- if pygments is None:
- code_block += nodes.Text(content, content)
- else:
- # The [:-1] is because pygments adds a trailing \n which looks bad
- 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
- values = value.split("\n")
- # The first piece, pass as-is
- code_block += nodes.Text(values[0], values[0])
- # On the second and later pieces, insert \n and linenos
- linenos = list(range(lineno, lineno + len(values)))
- for chunk, ln in zip(values, linenos)[1:]:
- if ln <= total_lines:
- code_block += nodes.inline(fstr.format(ln),
- fstr.format(ln),
- classes=['linenumber'])
- code_block += nodes.Text(chunk, chunk)
- lineno += len(values) - 1
-
- elif cls in unstyled_tokens:
- # insert as Text to decrease the verbosity of the output.
- code_block += nodes.Text(value, value)
- else:
- code_block += nodes.inline(value, value, classes=[cls])
-
- return [code_block]
-
-# Custom argument validators
-# --------------------------
-# ::
-#
-# Move to separated module??
-
-
-def string_list(argument):
- """
- Converts a space- or comma-separated list of values into a python list
- of strings.
- (Directive option conversion function)
- Based in positive_int_list of docutils.parsers.rst.directives
- """
- if ',' in argument:
- entries = argument.split(',')
- else:
- entries = argument.split()
- return entries
-
-
-def string_bool(argument):
- """
- Converts True, true, False, False in python boolean values
- """
- if argument is None:
- msg = 'argument required but none supplied; choose "True" or "False"'
- raise ValueError(msg)
-
- elif argument.lower() == 'true':
- return True
- elif argument.lower() == 'false':
- return False
- else:
- raise ValueError('"{0}" unknown; choose from "True" or "False"'.format(
- argument))
-
-
-def csharp_unicodelevel(argument):
- return directives.choice(argument, ('none', 'basic', 'full'))
-
-
-def lhs_litstyle(argument):
- return directives.choice(argument, ('bird', 'latex'))
-
-
-def raw_compress(argument):
- return directives.choice(argument, ('gz', 'bz2'))
-
-
-def listings_directive(name, arguments, options, content, lineno,
- content_offset, block_text, state, state_machine):
- fname = arguments[0]
- options['include'] = os.path.join('listings', fname)
- target = urlunsplit(("link", 'listing', fname, '', ''))
- generated_nodes = [core.publish_doctree('`{0} <{1}>`_'.format(fname,
- target))[0]]
- 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)
-listings_directive.arguments = (2, 0, 1)
-code_block_directive.content = 1
-listings_directive.content = 1
-code_block_directive.options = {'include': directives.unchanged_required,
- 'start-at': directives.unchanged_required,
- 'end-at': directives.unchanged_required,
- 'start-after': directives.unchanged_required,
- 'end-before': directives.unchanged_required,
- 'linenos': directives.unchanged,
- 'linenos_offset': directives.unchanged,
- 'tab-width': directives.unchanged,
- # generic
- 'stripnl': string_bool,
- 'stripall': string_bool,
- 'ensurenl': string_bool,
- 'tabsize': directives.positive_int,
- 'encoding': directives.encoding,
- # Lua
- 'func_name_hightlighting': string_bool,
- 'disabled_modules': string_list,
- # Python Console
- 'python3': string_bool,
- # Delphi
- 'turbopascal': string_bool,
- 'delphi': string_bool,
- 'freepascal': string_bool,
- 'units': string_list,
- # Modula2
- 'pim': string_bool,
- 'iso': string_bool,
- 'objm2': string_bool,
- 'gm2ext': string_bool,
- # CSharp
- 'unicodelevel': csharp_unicodelevel,
- # Literate haskell
- 'litstyle': lhs_litstyle,
- # Raw
- 'compress': raw_compress,
- # Rst
- 'handlecodeblocks': string_bool,
- # Php
- 'startinline': string_bool,
- 'funcnamehighlighting': string_bool,
- 'disabledmodules': string_list,
- }
-
-listings_directive.options = copy(code_block_directive.options)
-listings_directive.options.pop('include')
-
-# .. _doctutils: http://docutils.sf.net/
-# .. _pygments: http://pygments.org/
-# .. _Using Pygments in ReST documents: http://pygments.org/docs/rstdirective/
-# .. _proof of concept:
-# http://article.gmane.org/gmane.text.docutils.user/3689
-#
-# Test output
-# -----------
-#
-# If called from the command line, call the docutils publisher to render the
-# input::
-
-if __name__ == '__main__':
- from docutils.core import publish_cmdline, default_description
- from docutils.parsers.rst import directives
- directives.register_directive('code-block', code_block_directive)
- description = "code-block directive test output" + default_description
- try:
- import locale
- locale.setlocale(locale.LC_ALL, '')
- except Exception:
- pass
- publish_cmdline(writer_name='html', description=description)
diff --git a/nikola/plugins/compile_rest/slides.py b/nikola/plugins/compile_rest/slides.py index f9901f5..57fb754 100644 --- a/nikola/plugins/compile_rest/slides.py +++ b/nikola/plugins/compile_rest/slides.py @@ -22,71 +22,44 @@ # OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE # SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -import json +from __future__ import unicode_literals 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, - "preloadImage": directives.uri, - "container": directives.unchanged, - "generateNextPrev": directives.flag, - "next": directives.unchanged, - "prev": directives.unchanged, - "pagination": directives.flag, - "generatePagination": directives.flag, - "paginationClass": directives.unchanged, - "currentClass": directives.unchanged, - "fadeSpeed": directives.positive_int, - "fadeEasing": directives.unchanged, - "slideSpeed": directives.positive_int, - "slideEasing": directives.unchanged, - "start": directives.positive_int, - "effect": directives.unchanged, - "crossfade": directives.flag, - "randomize": directives.flag, - "play": directives.positive_int, - "pause": directives.positive_int, - "hoverPause": directives.flag, - "autoHeight": directives.flag, - "autoHeightSpeed": directives.positive_int, - "bigTarget": directives.flag, - "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"): - if opt in self.options: - self.options[opt] = True - options = { - "autoHeight": True, - "bigTarget": True, - "paginationClass": "pager", - "currentClass": "slide-current" - } - options.update(self.options) - options = json.dumps(options) output = [] - output.append('<script> $(function(){ $("#slides").slides(' + options + - '); });' - '</script>') - output.append('<div id="slides" class="slides"><div ' - 'class="slides_container">') - for image in self.content: - output.append("""<div><img src="{0}"></div>""".format(image)) - output.append("""</div></div>""") - + output.append(""" + <div id="myCarousel" class="carousel slide"> + <ol class="carousel-indicators"> + """) + for i in range(len(self.content)): + if i == 0: + classname = 'class="active"' + else: + classname = '' + output.append(' <li data-target="#myCarousel" data-slide-to="{0}" {1}></li>'.format(i, classname)) + output.append("""</ol> + <div class="carousel-inner"> + """) + for i, image in enumerate(self.content): + if i == 0: + classname = "item active" + else: + classname = "item" + output.append("""<div class="{0}"><img src="{1}" alt="" style="margin: 0 auto 0 auto;"></div>""".format(classname, image)) + output.append("""</div> + <a class="left carousel-control" href="#myCarousel" data-slide="prev">‹</a> + <a class="right carousel-control" href="#myCarousel" data-slide="next">›</a> + </div>""") return [nodes.raw('', '\n'.join(output), format='html')] -directives.register_directive('slides', slides) +directives.register_directive('slides', Slides) diff --git a/nikola/plugins/compile_rest/soundcloud.py b/nikola/plugins/compile_rest/soundcloud.py index d47bebf..6bdd4d5 100644 --- a/nikola/plugins/compile_rest/soundcloud.py +++ b/nikola/plugins/compile_rest/soundcloud.py @@ -1,5 +1,9 @@ +# coding: utf8 + + from docutils import nodes -from docutils.parsers.rst import directives +from docutils.parsers.rst import Directive, directives + CODE = ("""<iframe width="{width}" height="{height}" scrolling="no" frameborder="no" @@ -8,25 +12,39 @@ src="https://w.soundcloud.com/player/?url=http://api.soundcloud.com/tracks/""" </iframe>""") -def soundcloud(name, args, options, content, lineno, - contentOffset, blockText, state, stateMachine): - """ Restructured text extension for inserting SoundCloud embedded music """ - string_vars = { - 'sid': content[0], - 'width': 600, - 'height': 160, - 'extra': '' +class SoundCloud(Directive): + """ Restructured text extension for inserting SoundCloud embedded music + + Usage: + .. soundcloud:: <sound id> + :height: 400 + :width: 600 + + """ + has_content = True + required_arguments = 1 + option_spec = { + 'width': directives.positive_int, + 'height': directives.positive_int, } - 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') - - return [nodes.raw('', CODE.format(**string_vars), format='html')] - -soundcloud.content = True -directives.register_directive('soundcloud', soundcloud) + + def run(self): + """ Required by the Directive interface. Create docutils nodes """ + self.check_content() + options = { + 'sid': self.arguments[0], + 'width': 600, + 'height': 160, + } + options.update(self.options) + return [nodes.raw('', CODE.format(**options), format='html')] + + def check_content(self): + """ Emit a deprecation warning if there is content """ + if self.content: + raise self.warning("This directive does not accept content. The " + "'key=value' format for options is deprecated, " + "use ':key: value' instead") + + +directives.register_directive('soundcloud', SoundCloud) diff --git a/nikola/plugins/compile_rest/vimeo.py b/nikola/plugins/compile_rest/vimeo.py index 34f2a50..c1dc143 100644 --- a/nikola/plugins/compile_rest/vimeo.py +++ b/nikola/plugins/compile_rest/vimeo.py @@ -1,3 +1,4 @@ +# coding: utf8 # Copyright (c) 2012 Roberto Alsina y otros. # Permission is hereby granted, free of charge, to any @@ -22,8 +23,9 @@ # 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 +from docutils.parsers.rst import Directive, directives try: import requests @@ -37,6 +39,7 @@ except ImportError: except ImportError: json = None + CODE = """<iframe src="http://player.vimeo.com/video/{vimeo_id}" width="{width}" height="{height}" frameborder="0" webkitAllowFullScreen mozallowfullscreen allowFullScreen> @@ -47,46 +50,69 @@ 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}' - '.json'.format(**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.format(**string_vars), format='html')] - -vimeo.content = True -directives.register_directive('vimeo', vimeo) +class Vimeo(Directive): + """ Restructured text extension for inserting vimeo embedded videos + + Usage: + .. vimeo:: 20241459 + :height: 400 + :width: 600 + + """ + has_content = True + required_arguments = 1 + option_spec = { + "width": directives.positive_int, + "height": directives.positive_int, + } + + # set to False for not querying the vimeo api for size + request_size = True + + def run(self): + self.check_content() + options = { + 'vimeo_id': self.arguments[0], + 'width': VIDEO_DEFAULT_WIDTH, + 'height': VIDEO_DEFAULT_HEIGHT, + } + if self.request_size: + self.check_modules() + self.set_video_size() + options.update(self.options) + return [nodes.raw('', CODE.format(**options), format='html')] + + def check_modules(self): + 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.") + + def set_video_size(self): + # Only need to make a connection if width and height aren't provided + if 'height' not in self.options or 'width' not in self.options: + self.options['height'] = VIDEO_DEFAULT_HEIGHT + self.options['width'] = VIDEO_DEFAULT_WIDTH + + if json: # we can attempt to retrieve video attributes from vimeo + try: + url = ('http://vimeo.com/api/v2/video/{0}' + '.json'.format(self.arguments[0])) + data = requests.get(url).text + video_attributes = json.loads(data)[0] + self.options['height'] = video_attributes['height'] + self.options['width'] = video_attributes['width'] + except Exception: + # fall back to the defaults + pass + + def check_content(self): + if self.content: + raise self.warning("This directive does not accept content. The " + "'key=value' format for options is deprecated, " + "use ':key: value' instead") + + +directives.register_directive('vimeo', Vimeo) diff --git a/nikola/plugins/compile_rest/youtube.py b/nikola/plugins/compile_rest/youtube.py index 30ac000..767be32 100644 --- a/nikola/plugins/compile_rest/youtube.py +++ b/nikola/plugins/compile_rest/youtube.py @@ -23,7 +23,8 @@ # SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. from docutils import nodes -from docutils.parsers.rst import directives +from docutils.parsers.rst import Directive, directives + CODE = """\ <iframe width="{width}" @@ -32,25 +33,37 @@ src="http://www.youtube.com/embed/{yid}?rel=0&hd=1&wmode=transparent" ></iframe>""" -def youtube(name, args, options, content, lineno, - contentOffset, blockText, state, stateMachine): - """ Restructured text extension for inserting youtube embedded videos """ - if len(content) == 0: - return - string_vars = { - 'yid': content[0], - 'width': 425, - 'height': 344, - 'extra': '' +class Youtube(Directive): + """ Restructured text extension for inserting youtube embedded videos + + Usage: + .. youtube:: lyViVmaBQDg + :height: 400 + :width: 600 + + """ + has_content = True + required_arguments = 1 + option_spec = { + "width": directives.positive_int, + "height": directives.positive_int, } - 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') - return [nodes.raw('', CODE.format(**string_vars), format='html')] -youtube.content = True -directives.register_directive('youtube', youtube) + + def run(self): + self.check_content() + options = { + 'yid': self.arguments[0], + 'width': 425, + 'height': 344, + } + options.update(self.options) + return [nodes.raw('', CODE.format(**options), format='html')] + + def check_content(self): + if self.content: + raise self.warning("This directive does not accept content. The " + "'key=value' format for options is deprecated, " + "use ':key: value' instead") + + +directives.register_directive('youtube', Youtube) |
