summaryrefslogtreecommitdiffstats
path: root/nikola/plugins/compile
diff options
context:
space:
mode:
authorLibravatarDererk <dererk@satellogic.com>2016-11-15 14:18:46 -0300
committerLibravatarDererk <dererk@satellogic.com>2016-11-15 14:18:46 -0300
commitffb671c61a24a9086343b54bad080e145ff33fc5 (patch)
tree2c5291f7a34edf4afdc8e07887a148291bfa3fa1 /nikola/plugins/compile
parent4e3224c012df9f74f010eb92203520515e8537b9 (diff)
New upstream version 7.8.1upstream/7.8.1
Diffstat (limited to 'nikola/plugins/compile')
-rw-r--r--nikola/plugins/compile/__init__.py2
-rw-r--r--nikola/plugins/compile/html.py14
-rw-r--r--nikola/plugins/compile/ipynb.py60
-rw-r--r--nikola/plugins/compile/markdown/__init__.py16
-rw-r--r--nikola/plugins/compile/markdown/mdx_gist.py155
-rw-r--r--nikola/plugins/compile/markdown/mdx_nikola.py2
-rw-r--r--nikola/plugins/compile/markdown/mdx_podcast.py2
-rw-r--r--nikola/plugins/compile/pandoc.py17
-rw-r--r--nikola/plugins/compile/php.py2
-rw-r--r--nikola/plugins/compile/rest/__init__.py96
-rw-r--r--nikola/plugins/compile/rest/chart.py103
-rw-r--r--nikola/plugins/compile/rest/doc.py52
-rw-r--r--nikola/plugins/compile/rest/listing.py8
-rw-r--r--nikola/plugins/compile/rest/media.py17
-rw-r--r--nikola/plugins/compile/rest/post_list.py233
-rw-r--r--nikola/plugins/compile/rest/slides.py2
-rw-r--r--nikola/plugins/compile/rest/soundcloud.py17
-rw-r--r--nikola/plugins/compile/rest/thumbnail.py2
-rw-r--r--nikola/plugins/compile/rest/vimeo.py14
-rw-r--r--nikola/plugins/compile/rest/youtube.py18
20 files changed, 500 insertions, 332 deletions
diff --git a/nikola/plugins/compile/__init__.py b/nikola/plugins/compile/__init__.py
index 60f1919..ff7e9a2 100644
--- a/nikola/plugins/compile/__init__.py
+++ b/nikola/plugins/compile/__init__.py
@@ -1,6 +1,6 @@
# -*- coding: utf-8 -*-
-# Copyright © 2012-2015 Roberto Alsina and others.
+# Copyright © 2012-2016 Roberto Alsina and others.
# Permission is hereby granted, free of charge, to any
# person obtaining a copy of this software and associated
diff --git a/nikola/plugins/compile/html.py b/nikola/plugins/compile/html.py
index 6ff5de8..942d6da 100644
--- a/nikola/plugins/compile/html.py
+++ b/nikola/plugins/compile/html.py
@@ -1,6 +1,6 @@
# -*- coding: utf-8 -*-
-# Copyright © 2012-2015 Roberto Alsina and others.
+# Copyright © 2012-2016 Roberto Alsina and others.
# Permission is hereby granted, free of charge, to any
# person obtaining a copy of this software and associated
@@ -44,12 +44,24 @@ class CompileHtml(PageCompiler):
def compile_html(self, source, dest, is_two_file=True):
"""Compile source file into HTML and save as dest."""
makedirs(os.path.dirname(dest))
+ try:
+ post = self.site.post_per_input_file[source]
+ except KeyError:
+ post = None
with io.open(dest, "w+", encoding="utf8") as out_file:
with io.open(source, "r", encoding="utf8") as in_file:
data = in_file.read()
if not is_two_file:
_, data = self.split_metadata(data)
+ data, shortcode_deps = self.site.apply_shortcodes(data, with_dependencies=True, extra_context=dict(post=post))
out_file.write(data)
+ if post is None:
+ if shortcode_deps:
+ self.logger.error(
+ "Cannot save dependencies for post {0} due to unregistered source file name",
+ source)
+ else:
+ post._depfile[dest] += shortcode_deps
return True
def create_post(self, path, **kw):
diff --git a/nikola/plugins/compile/ipynb.py b/nikola/plugins/compile/ipynb.py
index 1023b31..f3fdeea 100644
--- a/nikola/plugins/compile/ipynb.py
+++ b/nikola/plugins/compile/ipynb.py
@@ -1,6 +1,6 @@
# -*- coding: utf-8 -*-
-# Copyright © 2013-2015 Damián Avila, Chris Warrick and others.
+# Copyright © 2013-2016 Damián Avila, Chris Warrick and others.
# Permission is hereby granted, free of charge, to any
# person obtaining a copy of this software and associated
@@ -32,21 +32,33 @@ import os
import sys
try:
- import IPython
- from IPython.nbconvert.exporters import HTMLExporter
- if IPython.version_info[0] >= 3: # API changed with 3.0.0
- from IPython import nbformat
- current_nbformat = nbformat.current_nbformat
- from IPython.kernel import kernelspec
- else:
- import IPython.nbformat.current as nbformat
- current_nbformat = 'json'
- kernelspec = None
-
- from IPython.config import Config
+ from nbconvert.exporters import HTMLExporter
+ import nbformat
+ current_nbformat = nbformat.current_nbformat
+ from jupyter_client import kernelspec
+ from traitlets.config import Config
flag = True
+ ipy_modern = True
except ImportError:
- flag = None
+ try:
+ import IPython
+ from IPython.nbconvert.exporters import HTMLExporter
+ if IPython.version_info[0] >= 3: # API changed with 3.0.0
+ from IPython import nbformat
+ current_nbformat = nbformat.current_nbformat
+ from IPython.kernel import kernelspec
+ ipy_modern = True
+ else:
+ import IPython.nbformat.current as nbformat
+ current_nbformat = 'json'
+ kernelspec = None
+ ipy_modern = False
+
+ from IPython.config import Config
+ flag = True
+ except ImportError:
+ flag = None
+ ipy_modern = None
from nikola.plugin_categories import PageCompiler
from nikola.utils import makedirs, req_missing, get_logger, STDERR_HANDLER
@@ -69,7 +81,6 @@ class CompileIPynb(PageCompiler):
"""Export notebooks as HTML strings."""
if flag is None:
req_missing(['ipython[notebook]>=2.0.0'], 'build this site (compile ipynb)')
- HTMLExporter.default_template = 'basic'
c = Config(self.site.config['IPYNB_CONFIG'])
exportHtml = HTMLExporter(config=c)
with io.open(source, "r", encoding="utf8") as in_file:
@@ -80,8 +91,21 @@ class CompileIPynb(PageCompiler):
def compile_html(self, source, dest, is_two_file=True):
"""Compile source file into HTML and save as dest."""
makedirs(os.path.dirname(dest))
+ try:
+ post = self.site.post_per_input_file[source]
+ except KeyError:
+ post = None
with io.open(dest, "w+", encoding="utf8") as out_file:
- out_file.write(self.compile_html_string(source, is_two_file))
+ output = self.compile_html_string(source, is_two_file)
+ output, shortcode_deps = self.site.apply_shortcodes(output, filename=source, with_dependencies=True, extra_context=dict(post=post))
+ out_file.write(output)
+ if post is None:
+ if shortcode_deps:
+ self.logger.error(
+ "Cannot save dependencies for post {0} due to unregistered source file name",
+ source)
+ else:
+ post._depfile[dest] += shortcode_deps
def read_metadata(self, post, file_metadata_regexp=None, unslugify_titles=False, lang=None):
"""Read metadata directly from ipynb file.
@@ -118,7 +142,7 @@ class CompileIPynb(PageCompiler):
# imported .ipynb file, guaranteed to start with "{" because it’s JSON.
nb = nbformat.reads(content, current_nbformat)
else:
- if IPython.version_info[0] >= 3:
+ if ipy_modern:
nb = nbformat.v4.new_notebook()
nb["cells"] = [nbformat.v4.new_markdown_cell(content)]
else:
@@ -151,7 +175,7 @@ class CompileIPynb(PageCompiler):
nb["metadata"]["nikola"] = metadata
with io.open(path, "w+", encoding="utf8") as fd:
- if IPython.version_info[0] >= 3:
+ if ipy_modern:
nbformat.write(nb, fd, 4)
else:
nbformat.write(nb, fd, 'ipynb')
diff --git a/nikola/plugins/compile/markdown/__init__.py b/nikola/plugins/compile/markdown/__init__.py
index 93438a3..2e4234c 100644
--- a/nikola/plugins/compile/markdown/__init__.py
+++ b/nikola/plugins/compile/markdown/__init__.py
@@ -1,6 +1,6 @@
# -*- coding: utf-8 -*-
-# Copyright © 2012-2015 Roberto Alsina and others.
+# Copyright © 2012-2016 Roberto Alsina and others.
# Permission is hereby granted, free of charge, to any
# person obtaining a copy of this software and associated
@@ -69,13 +69,25 @@ class CompileMarkdown(PageCompiler):
req_missing(['markdown'], 'build this site (compile Markdown)')
makedirs(os.path.dirname(dest))
self.extensions += self.site.config.get("MARKDOWN_EXTENSIONS")
+ try:
+ post = self.site.post_per_input_file[source]
+ except KeyError:
+ post = None
with io.open(dest, "w+", encoding="utf8") as out_file:
with io.open(source, "r", encoding="utf8") as in_file:
data = in_file.read()
if not is_two_file:
_, data = self.split_metadata(data)
- output = markdown(data, self.extensions)
+ output = markdown(data, self.extensions, output_format="html5")
+ output, shortcode_deps = self.site.apply_shortcodes(output, filename=source, with_dependencies=True, extra_context=dict(post=post))
out_file.write(output)
+ if post is None:
+ if shortcode_deps:
+ self.logger.error(
+ "Cannot save dependencies for post {0} due to unregistered source file name",
+ source)
+ else:
+ post._depfile[dest] += shortcode_deps
def create_post(self, path, **kw):
"""Create a new post."""
diff --git a/nikola/plugins/compile/markdown/mdx_gist.py b/nikola/plugins/compile/markdown/mdx_gist.py
index a930de5..25c071f 100644
--- a/nikola/plugins/compile/markdown/mdx_gist.py
+++ b/nikola/plugins/compile/markdown/mdx_gist.py
@@ -31,161 +31,48 @@ Extension to Python Markdown for Embedded Gists (gist.github.com).
Basic Example:
- >>> import markdown
- >>> text = '''
- ... Text of the gist:
- ... [:gist: 4747847]
- ... '''
- >>> html = markdown.markdown(text, [GistExtension()])
- >>> print(html)
- <p>Text of the gist:
- <div class="gist">
- <script src="https://gist.github.com/4747847.js"></script>
- <noscript>
- <pre>import this</pre>
- </noscript>
- </div>
- </p>
+ Text of the gist:
+ [:gist: 4747847]
Example with filename:
- >>> import markdown
- >>> text = '''
- ... Text of the gist:
- ... [:gist: 4747847 zen.py]
- ... '''
- >>> html = markdown.markdown(text, [GistExtension()])
- >>> print(html)
- <p>Text of the gist:
- <div class="gist">
- <script src="https://gist.github.com/4747847.js?file=zen.py"></script>
- <noscript>
- <pre>import this</pre>
- </noscript>
- </div>
- </p>
+ Text of the gist:
+ [:gist: 4747847 zen.py]
Basic Example with hexidecimal id:
- >>> import markdown
- >>> text = '''
- ... Text of the gist:
- ... [:gist: c4a43d6fdce612284ac0]
- ... '''
- >>> html = markdown.markdown(text, [GistExtension()])
- >>> print(html)
- <p>Text of the gist:
- <div class="gist">
- <script src="https://gist.github.com/c4a43d6fdce612284ac0.js"></script>
- <noscript>
- <pre>Moo</pre>
- </noscript>
- </div>
- </p>
+ Text of the gist:
+ [:gist: c4a43d6fdce612284ac0]
Example with hexidecimal id filename:
- >>> import markdown
- >>> text = '''
- ... Text of the gist:
- ... [:gist: c4a43d6fdce612284ac0 cow.txt]
- ... '''
- >>> html = markdown.markdown(text, [GistExtension()])
- >>> print(html)
- <p>Text of the gist:
- <div class="gist">
- <script src="https://gist.github.com/c4a43d6fdce612284ac0.js?file=cow.txt"></script>
- <noscript>
- <pre>Moo</pre>
- </noscript>
- </div>
- </p>
+ Text of the gist:
+ [:gist: c4a43d6fdce612284ac0 cow.txt]
Example using reStructuredText syntax:
- >>> import markdown
- >>> text = '''
- ... Text of the gist:
- ... .. gist:: 4747847 zen.py
- ... '''
- >>> html = markdown.markdown(text, [GistExtension()])
- >>> print(html)
- <p>Text of the gist:
- <div class="gist">
- <script src="https://gist.github.com/4747847.js?file=zen.py"></script>
- <noscript>
- <pre>import this</pre>
- </noscript>
- </div>
- </p>
+ Text of the gist:
+ .. gist:: 4747847 zen.py
Example using hexidecimal ID with reStructuredText syntax:
- >>> import markdown
- >>> text = '''
- ... Text of the gist:
- ... .. gist:: c4a43d6fdce612284ac0
- ... '''
- >>> html = markdown.markdown(text, [GistExtension()])
- >>> print(html)
- <p>Text of the gist:
- <div class="gist">
- <script src="https://gist.github.com/c4a43d6fdce612284ac0.js"></script>
- <noscript>
- <pre>Moo</pre>
- </noscript>
- </div>
- </p>
+ Text of the gist:
+ .. gist:: c4a43d6fdce612284ac0
Example using hexidecimal ID and filename with reStructuredText syntax:
- >>> import markdown
- >>> text = '''
- ... Text of the gist:
- ... .. gist:: c4a43d6fdce612284ac0 cow.txt
- ... '''
- >>> html = markdown.markdown(text, [GistExtension()])
- >>> print(html)
- <p>Text of the gist:
- <div class="gist">
- <script src="https://gist.github.com/c4a43d6fdce612284ac0.js?file=cow.txt"></script>
- <noscript>
- <pre>Moo</pre>
- </noscript>
- </div>
- </p>
+ Text of the gist:
+ .. gist:: c4a43d6fdce612284ac0 cow.txt
Error Case: non-existent Gist ID:
- >>> import markdown
- >>> text = '''
- ... Text of the gist:
- ... [:gist: 0]
- ... '''
- >>> html = markdown.markdown(text, [GistExtension()])
- >>> print(html)
- <p>Text of the gist:
- <div class="gist">
- <script src="https://gist.github.com/0.js"></script>
- <noscript><!-- WARNING: Received a 404 response from Gist URL: https://gist.githubusercontent.com/raw/0 --></noscript>
- </div>
- </p>
-
-Error Case: non-existent file:
-
- >>> import markdown
- >>> text = '''
- ... Text of the gist:
- ... [:gist: 4747847 doesntexist.py]
- ... '''
- >>> html = markdown.markdown(text, [GistExtension()])
- >>> print(html)
- <p>Text of the gist:
- <div class="gist">
- <script src="https://gist.github.com/4747847.js?file=doesntexist.py"></script>
- <noscript><!-- WARNING: Received a 404 response from Gist URL: https://gist.githubusercontent.com/raw/4747847/doesntexist.py --></noscript>
- </div>
- </p>
+ Text of the gist:
+ [:gist: 0]
+
+Error Case: non-existent file:
+
+ Text of the gist:
+ [:gist: 4747847 doesntexist.py]
"""
from __future__ import unicode_literals, print_function
diff --git a/nikola/plugins/compile/markdown/mdx_nikola.py b/nikola/plugins/compile/markdown/mdx_nikola.py
index 7984121..59a5d5b 100644
--- a/nikola/plugins/compile/markdown/mdx_nikola.py
+++ b/nikola/plugins/compile/markdown/mdx_nikola.py
@@ -1,6 +1,6 @@
# -*- coding: utf-8 -*-
-# Copyright © 2012-2015 Roberto Alsina and others.
+# Copyright © 2012-2016 Roberto Alsina and others.
# Permission is hereby granted, free of charge, to any
# person obtaining a copy of this software and associated
diff --git a/nikola/plugins/compile/markdown/mdx_podcast.py b/nikola/plugins/compile/markdown/mdx_podcast.py
index 0f68e40..96a70ed 100644
--- a/nikola/plugins/compile/markdown/mdx_podcast.py
+++ b/nikola/plugins/compile/markdown/mdx_podcast.py
@@ -1,6 +1,6 @@
# -*- coding: utf-8 -*-
#
-# Copyright © 2013-2015 Michael Rabbitt, Roberto Alsina and others.
+# Copyright © 2013-2016 Michael Rabbitt, Roberto Alsina and others.
#
# Permission is hereby granted, free of charge, to any person obtaining a
# copy of this software and associated documentation files (the
diff --git a/nikola/plugins/compile/pandoc.py b/nikola/plugins/compile/pandoc.py
index 85e84fc..2368ae9 100644
--- a/nikola/plugins/compile/pandoc.py
+++ b/nikola/plugins/compile/pandoc.py
@@ -1,6 +1,6 @@
# -*- coding: utf-8 -*-
-# Copyright © 2012-2015 Roberto Alsina and others.
+# Copyright © 2012-2016 Roberto Alsina and others.
# Permission is hereby granted, free of charge, to any
# person obtaining a copy of this software and associated
@@ -54,7 +54,22 @@ class CompilePandoc(PageCompiler):
"""Compile source file into HTML and save as dest."""
makedirs(os.path.dirname(dest))
try:
+ try:
+ post = self.site.post_per_input_file[source]
+ except KeyError:
+ post = None
subprocess.check_call(['pandoc', '-o', dest, source] + self.site.config['PANDOC_OPTIONS'])
+ with open(dest, 'r', encoding='utf-8') as inf:
+ output, shortcode_deps = self.site.apply_shortcodes(inf.read(), with_dependencies=True)
+ with open(dest, 'w', encoding='utf-8') as outf:
+ outf.write(output)
+ if post is None:
+ if shortcode_deps:
+ self.logger.error(
+ "Cannot save dependencies for post {0} due to unregistered source file name",
+ source)
+ else:
+ post._depfile[dest] += shortcode_deps
except OSError as e:
if e.strreror == 'No such file or directory':
req_missing(['pandoc'], 'build this site (compile with pandoc)', python=False)
diff --git a/nikola/plugins/compile/php.py b/nikola/plugins/compile/php.py
index a60e31a..d2559fd 100644
--- a/nikola/plugins/compile/php.py
+++ b/nikola/plugins/compile/php.py
@@ -1,6 +1,6 @@
# -*- coding: utf-8 -*-
-# Copyright © 2012-2015 Roberto Alsina and others.
+# Copyright © 2012-2016 Roberto Alsina and others.
# Permission is hereby granted, free of charge, to any
# person obtaining a copy of this software and associated
diff --git a/nikola/plugins/compile/rest/__init__.py b/nikola/plugins/compile/rest/__init__.py
index 4b04958..b75849f 100644
--- a/nikola/plugins/compile/rest/__init__.py
+++ b/nikola/plugins/compile/rest/__init__.py
@@ -1,6 +1,6 @@
# -*- coding: utf-8 -*-
-# Copyright © 2012-2015 Roberto Alsina and others.
+# Copyright © 2012-2016 Roberto Alsina and others.
# Permission is hereby granted, free of charge, to any
# person obtaining a copy of this software and associated
@@ -36,9 +36,19 @@ import docutils.utils
import docutils.io
import docutils.readers.standalone
import docutils.writers.html4css1
+import docutils.parsers.rst.directives
+from docutils.parsers.rst import roles
+from nikola.nikola import LEGAL_VALUES
from nikola.plugin_categories import PageCompiler
-from nikola.utils import unicode_str, get_logger, makedirs, write_metadata, STDERR_HANDLER
+from nikola.utils import (
+ unicode_str,
+ get_logger,
+ makedirs,
+ write_metadata,
+ STDERR_HANDLER,
+ LocaleBorg
+)
class CompileRest(PageCompiler):
@@ -49,19 +59,6 @@ class CompileRest(PageCompiler):
demote_headers = True
logger = None
- def _read_extra_deps(self, post):
- """Read contents of .dep file and returns them as a list."""
- dep_path = post.base_path + '.dep'
- if os.path.isfile(dep_path):
- with io.open(dep_path, 'r+', encoding='utf8') as depf:
- deps = [l.strip() for l in depf.readlines()]
- return deps
- return []
-
- def register_extra_dependencies(self, post):
- """Add dependency to post object to check .dep file."""
- post.add_dependency(lambda: self._read_extra_deps(post), 'fragment')
-
def compile_html_string(self, data, source_path=None, is_two_file=True):
"""Compile reST into HTML strings."""
# If errors occur, this will be added to the line number reported by
@@ -73,16 +70,20 @@ class CompileRest(PageCompiler):
add_ln = len(m_data.splitlines()) + 1
default_template_path = os.path.join(os.path.dirname(__file__), 'template.txt')
+ settings_overrides = {
+ 'initial_header_level': 1,
+ 'record_dependencies': True,
+ 'stylesheet_path': None,
+ 'link_stylesheet': True,
+ 'syntax_highlight': 'short',
+ 'math_output': 'mathjax',
+ 'template': default_template_path,
+ 'language_code': LEGAL_VALUES['DOCUTILS_LOCALES'].get(LocaleBorg().current_lang, 'en')
+ }
+
output, error_level, deps = rst2html(
- data, settings_overrides={
- 'initial_header_level': 1,
- 'record_dependencies': True,
- 'stylesheet_path': None,
- 'link_stylesheet': True,
- 'syntax_highlight': 'short',
- 'math_output': 'mathjax',
- 'template': default_template_path,
- }, logger=self.logger, source_path=source_path, l_add_ln=add_ln, transforms=self.site.rst_transforms)
+ data, settings_overrides=settings_overrides, logger=self.logger, source_path=source_path, l_add_ln=add_ln, transforms=self.site.rst_transforms,
+ no_title_transform=self.site.config.get('NO_DOCUTILS_TITLE_TRANSFORM', False))
if not isinstance(output, unicode_str):
# To prevent some weird bugs here or there.
# Original issue: empty files. `output` became a bytestring.
@@ -94,18 +95,23 @@ class CompileRest(PageCompiler):
makedirs(os.path.dirname(dest))
error_level = 100
with io.open(dest, "w+", encoding="utf8") as out_file:
+ try:
+ post = self.site.post_per_input_file[source]
+ except KeyError:
+ post = None
with io.open(source, "r", encoding="utf8") as in_file:
data = in_file.read()
output, error_level, deps = self.compile_html_string(data, source, is_two_file)
+ output, shortcode_deps = self.site.apply_shortcodes(output, filename=source, with_dependencies=True, extra_context=dict(post=post))
out_file.write(output)
- deps_path = dest + '.dep'
- if deps.list:
- deps.list = [p for p in deps.list if p != dest] # Don't depend on yourself (#1671)
- with io.open(deps_path, "w+", encoding="utf8") as deps_file:
- deps_file.write('\n'.join(deps.list))
+ if post is None:
+ if deps.list:
+ self.logger.error(
+ "Cannot save dependencies for post {0} due to unregistered source file name",
+ source)
else:
- if os.path.isfile(deps_path):
- os.unlink(deps_path)
+ post._depfile[dest] += deps.list
+ post._depfile[dest] += shortcode_deps
if error_level < 3:
return True
else:
@@ -176,11 +182,15 @@ class NikolaReader(docutils.readers.standalone.Reader):
def __init__(self, *args, **kwargs):
"""Initialize the reader."""
self.transforms = kwargs.pop('transforms', [])
+ self.no_title_transform = kwargs.pop('no_title_transform', False)
docutils.readers.standalone.Reader.__init__(self, *args, **kwargs)
def get_transforms(self):
"""Get docutils transforms."""
- return docutils.readers.standalone.Reader(self).get_transforms() + self.transforms
+ transforms = docutils.readers.standalone.Reader(self).get_transforms() + self.transforms
+ if self.no_title_transform:
+ transforms = [t for t in transforms if str(t) != "<class 'docutils.transforms.frontmatter.DocTitle'>"]
+ return transforms
def new_document(self):
"""Create and return a new empty document tree (root node)."""
@@ -190,6 +200,16 @@ class NikolaReader(docutils.readers.standalone.Reader):
return document
+def shortcode_role(name, rawtext, text, lineno, inliner,
+ options={}, content=[]):
+ """A shortcode role that passes through raw inline HTML."""
+ return [docutils.nodes.raw('', text, format='html')], []
+
+roles.register_canonical_role('raw-html', shortcode_role)
+roles.register_canonical_role('html', shortcode_role)
+roles.register_canonical_role('sc', shortcode_role)
+
+
def add_node(node, visit_function=None, depart_function=None):
"""Register a Docutils node class.
@@ -235,7 +255,8 @@ def rst2html(source, source_path=None, source_class=docutils.io.StringInput,
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, logger=None, l_add_ln=0, transforms=None):
+ enable_exit_status=None, logger=None, l_add_ln=0, transforms=None,
+ no_title_transform=False):
"""Set up & run a ``Publisher``, and return a dictionary of document parts.
Dictionary keys are the names of parts, and values are Unicode strings;
@@ -253,7 +274,7 @@ def rst2html(source, source_path=None, source_class=docutils.io.StringInput,
reStructuredText syntax errors.
"""
if reader is None:
- reader = NikolaReader(transforms=transforms)
+ reader = NikolaReader(transforms=transforms, no_title_transform=no_title_transform)
# For our custom logging, we have special needs and special settings we
# specify here.
# logger a logger from Nikola
@@ -274,3 +295,10 @@ def rst2html(source, source_path=None, source_class=docutils.io.StringInput,
pub.publish(enable_exit_status=enable_exit_status)
return pub.writer.parts['docinfo'] + pub.writer.parts['fragment'], pub.document.reporter.max_level, pub.settings.record_dependencies
+
+# Alignment helpers for extensions
+_align_options_base = ('left', 'center', 'right')
+
+
+def _align_choice(argument):
+ return docutils.parsers.rst.directives.choice(argument, _align_options_base + ("none", ""))
diff --git a/nikola/plugins/compile/rest/chart.py b/nikola/plugins/compile/rest/chart.py
index ed8a250..24f459b 100644
--- a/nikola/plugins/compile/rest/chart.py
+++ b/nikola/plugins/compile/rest/chart.py
@@ -1,6 +1,6 @@
# -*- coding: utf-8 -*-
-# Copyright © 2012-2015 Roberto Alsina and others.
+# Copyright © 2012-2016 Roberto Alsina and others.
# Permission is hereby granted, free of charge, to any
# person obtaining a copy of this software and associated
@@ -52,6 +52,7 @@ class Plugin(RestExtension):
global _site
_site = self.site = site
directives.register_directive('chart', Chart)
+ self.site.register_shortcode('chart', _gen_chart)
return super(Plugin, self).set_site(site)
@@ -72,52 +73,68 @@ class Chart(Directive):
has_content = True
required_arguments = 1
option_spec = {
- "copy": directives.unchanged,
+ "box_mode": directives.unchanged,
+ "classes": directives.unchanged,
"css": directives.unchanged,
+ "defs": directives.unchanged,
"disable_xml_declaration": directives.unchanged,
"dots_size": directives.unchanged,
+ "dynamic_print_values": directives.unchanged,
"explicit_size": directives.unchanged,
"fill": directives.unchanged,
- "font_sizes": directives.unchanged,
+ "force_uri_protocol": directives.unchanged,
+ "half_pie": directives.unchanged,
"height": directives.unchanged,
"human_readable": directives.unchanged,
"include_x_axis": directives.unchanged,
+ "inner_radius": directives.unchanged,
"interpolate": directives.unchanged,
"interpolation_parameters": directives.unchanged,
"interpolation_precision": directives.unchanged,
+ "inverse_y_axis": directives.unchanged,
"js": directives.unchanged,
- "label_font_size": directives.unchanged,
"legend_at_bottom": directives.unchanged,
+ "legend_at_bottom_columns": directives.unchanged,
"legend_box_size": directives.unchanged,
- "legend_font_size": directives.unchanged,
"logarithmic": directives.unchanged,
- "major_label_font_size": directives.unchanged,
"margin": directives.unchanged,
- "no_data_font_size": directives.unchanged,
+ "margin_bottom": directives.unchanged,
+ "margin_left": directives.unchanged,
+ "margin_right": directives.unchanged,
+ "margin_top": directives.unchanged,
+ "max_scale": directives.unchanged,
+ "min_scale": directives.unchanged,
+ "missing_value_fill_truncation": directives.unchanged,
"no_data_text": directives.unchanged,
"no_prefix": directives.unchanged,
"order_min": directives.unchanged,
"pretty_print": directives.unchanged,
+ "print_labels": directives.unchanged,
"print_values": directives.unchanged,
+ "print_values_position": directives.unchanged,
"print_zeroes": directives.unchanged,
"range": directives.unchanged,
"rounded_bars": directives.unchanged,
+ "secondary_range": directives.unchanged,
"show_dots": directives.unchanged,
"show_legend": directives.unchanged,
"show_minor_x_labels": directives.unchanged,
+ "show_minor_y_labels": directives.unchanged,
+ "show_only_major_dots": directives.unchanged,
+ "show_x_guides": directives.unchanged,
+ "show_x_labels": directives.unchanged,
+ "show_y_guides": directives.unchanged,
"show_y_labels": directives.unchanged,
"spacing": directives.unchanged,
+ "stack_from_top": directives.unchanged,
"strict": directives.unchanged,
"stroke": directives.unchanged,
+ "stroke_style": directives.unchanged,
"style": directives.unchanged,
"title": directives.unchanged,
- "title_font_size": directives.unchanged,
- "to_dict": directives.unchanged,
"tooltip_border_radius": directives.unchanged,
- "tooltip_font_size": directives.unchanged,
"truncate_label": directives.unchanged,
"truncate_legend": directives.unchanged,
- "value_font_size": directives.unchanged,
"value_formatter": directives.unchanged,
"width": directives.unchanged,
"x_label_rotation": directives.unchanged,
@@ -126,37 +143,55 @@ class Chart(Directive):
"x_labels_major_count": directives.unchanged,
"x_labels_major_every": directives.unchanged,
"x_title": directives.unchanged,
+ "x_value_formatter": directives.unchanged,
+ "xrange": directives.unchanged,
"y_label_rotation": directives.unchanged,
"y_labels": directives.unchanged,
+ "y_labels_major": directives.unchanged,
+ "y_labels_major_count": directives.unchanged,
+ "y_labels_major_every": directives.unchanged,
"y_title": directives.unchanged,
"zero": directives.unchanged,
}
def run(self):
"""Run the directive."""
- if pygal is None:
- msg = req_missing(['pygal'], 'use the Chart directive', optional=True)
- return [nodes.raw('', '<div class="text-error">{0}</div>'.format(msg), format='html')]
- options = {}
- if 'style' in self.options:
- style_name = self.options.pop('style')
- else:
- style_name = 'BlueStyle'
- if '(' in style_name: # Parametric style
- style = eval('pygal.style.' + style_name)
- else:
- style = getattr(pygal.style, style_name)
- for k, v in self.options.items():
+ self.options['site'] = None
+ html = _gen_chart(self.arguments[0], data='\n'.join(self.content), **self.options)
+ return [nodes.raw('', html, format='html')]
+
+
+def _gen_chart(chart_type, **_options):
+ if pygal is None:
+ msg = req_missing(['pygal'], 'use the Chart directive', optional=True)
+ return '<div class="text-error">{0}</div>'.format(msg)
+ options = {}
+ data = _options.pop('data')
+ _options.pop('post', None)
+ _options.pop('site')
+ if 'style' in _options:
+ style_name = _options.pop('style')
+ else:
+ style_name = 'BlueStyle'
+ if '(' in style_name: # Parametric style
+ style = eval('pygal.style.' + style_name)
+ else:
+ style = getattr(pygal.style, style_name)
+ for k, v in _options.items():
+ try:
options[k] = literal_eval(v)
- chart = pygal
- for o in self.arguments[0].split('.'):
- chart = getattr(chart, o)
- chart = chart(style=style)
- if _site and _site.invariant:
- chart.no_prefix = True
- chart.config(**options)
- for line in self.content:
+ except:
+ options[k] = v
+ chart = pygal
+ for o in chart_type.split('.'):
+ chart = getattr(chart, o)
+ chart = chart(style=style)
+ if _site and _site.invariant:
+ chart.no_prefix = True
+ chart.config(**options)
+ for line in data.splitlines():
+ line = line.strip()
+ if line:
label, series = literal_eval('({0})'.format(line))
chart.add(label, series)
- data = chart.render().decode('utf8')
- return [nodes.raw('', data, format='html')]
+ return chart.render().decode('utf8')
diff --git a/nikola/plugins/compile/rest/doc.py b/nikola/plugins/compile/rest/doc.py
index 578f012..55f576d 100644
--- a/nikola/plugins/compile/rest/doc.py
+++ b/nikola/plugins/compile/rest/doc.py
@@ -1,6 +1,6 @@
# -*- coding: utf-8 -*-
-# Copyright © 2012-2015 Roberto Alsina and others.
+# Copyright © 2012-2016 Roberto Alsina and others.
# Permission is hereby granted, free of charge, to any
# person obtaining a copy of this software and associated
@@ -29,7 +29,7 @@
from docutils import nodes
from docutils.parsers.rst import roles
-from nikola.utils import split_explicit_title
+from nikola.utils import split_explicit_title, LOGGER
from nikola.plugin_categories import RestExtension
@@ -42,12 +42,12 @@ class Plugin(RestExtension):
"""Set Nikola site."""
self.site = site
roles.register_canonical_role('doc', doc_role)
+ self.site.register_shortcode('doc', doc_shortcode)
doc_role.site = site
return super(Plugin, self).set_site(site)
-def doc_role(name, rawtext, text, lineno, inliner,
- options={}, content=[]):
+def _doc_link(rawtext, text, options={}, content=[]):
"""Handle the doc role."""
# split link's text and post's slug in role content
has_explicit_title, title, slug = split_explicit_title(text)
@@ -66,22 +66,48 @@ def doc_role(name, rawtext, text, lineno, inliner,
if post is None:
raise ValueError
except ValueError:
+ return False, False, None, None, slug
+
+ if not has_explicit_title:
+ # use post's title as link's text
+ title = post.title()
+ permalink = post.permalink()
+
+ return True, twin_slugs, title, permalink, slug
+
+
+def doc_role(name, rawtext, text, lineno, inliner, options={}, content=[]):
+ """Handle the doc role."""
+ success, twin_slugs, title, permalink, slug = _doc_link(rawtext, text, options, content)
+ if success:
+ if twin_slugs:
+ inliner.reporter.warning(
+ 'More than one post with the same slug. Using "{0}"'.format(permalink))
+ LOGGER.warn(
+ 'More than one post with the same slug. Using "{0}" for doc role'.format(permalink))
+ node = make_link_node(rawtext, title, permalink, options)
+ return [node], []
+ else:
msg = inliner.reporter.error(
'"{0}" slug doesn\'t exist.'.format(slug),
line=lineno)
prb = inliner.problematic(rawtext, rawtext, msg)
return [prb], [msg]
- if not has_explicit_title:
- # use post's title as link's text
- title = post.title()
- permalink = post.permalink()
- if twin_slugs:
- msg = inliner.reporter.warning(
- 'More than one post with the same slug. Using "{0}"'.format(permalink))
- node = make_link_node(rawtext, title, permalink, options)
- return [node], []
+def doc_shortcode(*args, **kwargs):
+ """Implement the doc shortcode."""
+ text = kwargs['data']
+ success, twin_slugs, title, permalink, slug = _doc_link(text, text, LOGGER)
+ if success:
+ if twin_slugs:
+ LOGGER.warn(
+ 'More than one post with the same slug. Using "{0}" for doc shortcode'.format(permalink))
+ return '<a href="{0}">{1}</a>'.format(permalink, title)
+ else:
+ LOGGER.error(
+ '"{0}" slug doesn\'t exist.'.format(slug))
+ return '<span class="error text-error" style="color: red;">Invalid link: {0}</span>'.format(text)
def make_link_node(rawtext, text, url, options):
diff --git a/nikola/plugins/compile/rest/listing.py b/nikola/plugins/compile/rest/listing.py
index 07f1686..4dfbedc 100644
--- a/nikola/plugins/compile/rest/listing.py
+++ b/nikola/plugins/compile/rest/listing.py
@@ -1,6 +1,6 @@
# -*- coding: utf-8 -*-
-# Copyright © 2012-2015 Roberto Alsina and others.
+# Copyright © 2012-2016 Roberto Alsina and others.
# Permission is hereby granted, free of charge, to any
# person obtaining a copy of this software and associated
@@ -136,6 +136,7 @@ class Plugin(RestExtension):
# leaving these to make the code directive work with
# docutils < 0.9
CodeBlock.site = site
+ Listing.site = site
directives.register_directive('code', CodeBlock)
directives.register_directive('code-block', CodeBlock)
directives.register_directive('sourcecode', CodeBlock)
@@ -189,8 +190,11 @@ class Listing(Include):
self.content = fileobject.read().splitlines()
self.state.document.settings.record_dependencies.add(fpath)
target = urlunsplit(("link", 'listing', fpath.replace('\\', '/'), '', ''))
+ src_target = urlunsplit(("link", 'listing_source', fpath.replace('\\', '/'), '', ''))
+ src_label = self.site.MESSAGES('Source')
generated_nodes = (
- [core.publish_doctree('`{0} <{1}>`_'.format(_fname, target))[0]])
+ [core.publish_doctree('`{0} <{1}>`_ `({2}) <{3}>`_' .format(
+ _fname, target, src_label, src_target))[0]])
generated_nodes += self.get_code_from_file(fileobject)
return generated_nodes
diff --git a/nikola/plugins/compile/rest/media.py b/nikola/plugins/compile/rest/media.py
index d075e44..8a69586 100644
--- a/nikola/plugins/compile/rest/media.py
+++ b/nikola/plugins/compile/rest/media.py
@@ -1,6 +1,6 @@
# -*- coding: utf-8 -*-
-# Copyright © 2012-2015 Roberto Alsina and others.
+# Copyright © 2012-2016 Roberto Alsina and others.
# Permission is hereby granted, free of charge, to any
# person obtaining a copy of this software and associated
@@ -48,6 +48,7 @@ class Plugin(RestExtension):
"""Set Nikola site."""
self.site = site
directives.register_directive('media', Media)
+ self.site.register_shortcode('media', _gen_media_embed)
return super(Plugin, self).set_site(site)
@@ -60,9 +61,13 @@ class Media(Directive):
def run(self):
"""Run media directive."""
- if micawber is None:
- msg = req_missing(['micawber'], 'use the media directive', optional=True)
- return [nodes.raw('', '<div class="text-error">{0}</div>'.format(msg), format='html')]
+ html = _gen_media_embed(" ".join(self.arguments))
+ return [nodes.raw('', html, format='html')]
- providers = micawber.bootstrap_basic()
- return [nodes.raw('', micawber.parse_text(" ".join(self.arguments), providers), format='html')]
+
+def _gen_media_embed(url, *q, **kw):
+ if micawber is None:
+ msg = req_missing(['micawber'], 'use the media directive', optional=True)
+ return '<div class="text-error">{0}</div>'.format(msg)
+ providers = micawber.bootstrap_basic()
+ return micawber.parse_text(url, providers)
diff --git a/nikola/plugins/compile/rest/post_list.py b/nikola/plugins/compile/rest/post_list.py
index df9376b..8cfd5bf 100644
--- a/nikola/plugins/compile/rest/post_list.py
+++ b/nikola/plugins/compile/rest/post_list.py
@@ -1,6 +1,6 @@
# -*- coding: utf-8 -*-
-# Copyright © 2013-2015 Udo Spallek, Roberto Alsina and others.
+# Copyright © 2013-2016 Udo Spallek, Roberto Alsina and others.
# Permission is hereby granted, free of charge, to any
# person obtaining a copy of this software and associated
@@ -37,6 +37,7 @@ from docutils.parsers.rst import Directive, directives
from nikola import utils
from nikola.plugin_categories import RestExtension
+from nikola.packages.datecond import date_in_range
# WARNING: the directive name is post-list
# (with a DASH instead of an UNDERSCORE)
@@ -50,6 +51,7 @@ class Plugin(RestExtension):
def set_site(self, site):
"""Set Nikola site."""
self.site = site
+ self.site.register_shortcode('post-list', _do_post_list)
directives.register_directive('post-list', PostList)
PostList.site = site
return super(Plugin, self).set_site(site)
@@ -61,7 +63,7 @@ class PostList(Directive):
Post List
=========
:Directive Arguments: None.
- :Directive Options: lang, start, stop, reverse, sort, tags, categories, slugs, all, template, id
+ :Directive Options: lang, start, stop, reverse, sort, date, tags, categories, sections, slugs, post_type, all, template, id
:Directive Content: None.
The posts appearing in the list can be filtered by options.
@@ -85,10 +87,19 @@ class PostList(Directive):
Reverse the order of the post-list.
Defaults is to not reverse the order of posts.
- ``sort``: string
+ ``sort`` : string
Sort post list by one of each post's attributes, usually ``title`` or a
custom ``priority``. Defaults to None (chronological sorting).
+ ``date`` : string
+ Show posts that match date range specified by this option. Format:
+
+ * comma-separated clauses (AND)
+ * clause: attribute comparison_operator value (spaces optional)
+ * attribute: year, month, day, hour, month, second, weekday, isoweekday; or empty for full datetime
+ * comparison_operator: == != <= >= < >
+ * value: integer or dateutil-compatible date input
+
``tags`` : string [, string...]
Filter posts to show only posts having at least one of the ``tags``.
Defaults to None.
@@ -97,13 +108,21 @@ class PostList(Directive):
Filter posts to show only posts having one of the ``categories``.
Defaults to None.
+ ``sections`` : string [, string...]
+ Filter posts to show only posts having one of the ``sections``.
+ Defaults to None.
+
``slugs`` : string [, string...]
Filter posts to show only posts having at least one of the ``slugs``.
Defaults to None.
+ ``post_type`` (or ``type``) : string
+ Show only ``posts``, ``pages`` or ``all``.
+ Replaces ``all``. Defaults to ``posts``.
+
``all`` : flag
- Shows all posts and pages in the post list.
- Defaults to show only posts with set *use_in_feeds*.
+ (deprecated, use ``post_type`` instead)
+ Shows all posts and pages in the post list. Defaults to show only posts.
``lang`` : string
The language of post *titles* and *links*.
@@ -125,11 +144,15 @@ class PostList(Directive):
'sort': directives.unchanged,
'tags': directives.unchanged,
'categories': directives.unchanged,
+ 'sections': directives.unchanged,
'slugs': directives.unchanged,
+ 'post_type': directives.unchanged,
+ 'type': directives.unchanged,
'all': directives.flag,
'lang': directives.unchanged,
'template': directives.path,
'id': directives.unchanged,
+ 'date': directives.unchanged,
}
def run(self):
@@ -138,75 +161,151 @@ class PostList(Directive):
stop = self.options.get('stop')
reverse = self.options.get('reverse', False)
tags = self.options.get('tags')
- tags = [t.strip().lower() for t in tags.split(',')] if tags else []
categories = self.options.get('categories')
- categories = [c.strip().lower() for c in categories.split(',')] if categories else []
+ sections = self.options.get('sections')
slugs = self.options.get('slugs')
- slugs = [s.strip() for s in slugs.split(',')] if slugs else []
- show_all = self.options.get('all', False)
+ post_type = self.options.get('post_type')
+ type = self.options.get('type', False)
+ all = self.options.get('all', False)
lang = self.options.get('lang', utils.LocaleBorg().current_lang)
template = self.options.get('template', 'post_list_directive.tmpl')
sort = self.options.get('sort')
- if self.site.invariant: # for testing purposes
- post_list_id = self.options.get('id', 'post_list_' + 'fixedvaluethatisnotauuid')
- else:
- post_list_id = self.options.get('id', 'post_list_' + uuid.uuid4().hex)
+ date = self.options.get('date')
- filtered_timeline = []
- posts = []
- step = -1 if reverse is None else None
- if show_all is None:
- timeline = [p for p in self.site.timeline]
+ output, deps = _do_post_list(start, stop, reverse, tags, categories, sections, slugs, post_type, type,
+ all, lang, template, sort, state=self.state, site=self.site, date=date)
+ self.state.document.settings.record_dependencies.add("####MAGIC####TIMELINE")
+ for d in deps:
+ self.state.document.settings.record_dependencies.add(d)
+ if output:
+ return [nodes.raw('', output, format='html')]
else:
- timeline = [p for p in self.site.timeline if p.use_in_feeds]
-
- if categories:
- timeline = [p for p in timeline if p.meta('category', lang=lang).lower() in categories]
-
- for post in timeline:
- if tags:
- cont = True
- tags_lower = [t.lower() for t in post.tags]
- for tag in tags:
- if tag in tags_lower:
- cont = False
-
- if cont:
- continue
-
- filtered_timeline.append(post)
-
- if sort:
- filtered_timeline = natsort.natsorted(filtered_timeline, key=lambda post: post.meta[lang][sort], alg=natsort.ns.F | natsort.ns.IC)
-
- for post in filtered_timeline[start:stop:step]:
- if slugs:
- cont = True
- for slug in slugs:
- if slug == post.meta('slug'):
- cont = False
-
- if cont:
- continue
-
- bp = post.translated_base_path(lang)
- if os.path.exists(bp):
- self.state.document.settings.record_dependencies.add(bp)
+ return []
- posts += [post]
- if not posts:
- return []
- self.state.document.settings.record_dependencies.add("####MAGIC####TIMELINE")
+def _do_post_list(start=None, stop=None, reverse=False, tags=None, categories=None,
+ sections=None, slugs=None, post_type='post', type=False, all=False,
+ lang=None, template='post_list_directive.tmpl', sort=None,
+ id=None, data=None, state=None, site=None, date=None, filename=None, post=None):
+ if lang is None:
+ lang = utils.LocaleBorg().current_lang
+ if site.invariant: # for testing purposes
+ post_list_id = id or 'post_list_' + 'fixedvaluethatisnotauuid'
+ else:
+ post_list_id = id or 'post_list_' + uuid.uuid4().hex
+
+ # Get post from filename if available
+ if filename:
+ self_post = site.post_per_input_file.get(filename)
+ else:
+ self_post = None
+
+ if self_post:
+ self_post.register_depfile("####MAGIC####TIMELINE", lang=lang)
+
+ # If we get strings for start/stop, make them integers
+ if start is not None:
+ start = int(start)
+ if stop is not None:
+ stop = int(stop)
+
+ # Parse tags/categories/sections/slugs (input is strings)
+ tags = [t.strip().lower() for t in tags.split(',')] if tags else []
+ categories = [c.strip().lower() for c in categories.split(',')] if categories else []
+ sections = [s.strip().lower() for s in sections.split(',')] if sections else []
+ slugs = [s.strip() for s in slugs.split(',')] if slugs else []
+
+ filtered_timeline = []
+ posts = []
+ step = -1 if reverse is None else None
+
+ if type is not False:
+ post_type = type
+
+ # TODO: remove in v8
+ if all is not False:
+ timeline = [p for p in site.timeline]
+ elif post_type == 'page' or post_type == 'pages':
+ timeline = [p for p in site.timeline if not p.use_in_feeds]
+ elif post_type == 'all':
+ timeline = [p for p in site.timeline]
+ else: # post
+ timeline = [p for p in site.timeline if p.use_in_feeds]
+
+ # TODO: replaces all, uncomment in v8
+ # if post_type == 'page' or post_type == 'pages':
+ # timeline = [p for p in site.timeline if not p.use_in_feeds]
+ # elif post_type == 'all':
+ # timeline = [p for p in site.timeline]
+ # else: # post
+ # timeline = [p for p in site.timeline if p.use_in_feeds]
+
+ if categories:
+ timeline = [p for p in timeline if p.meta('category', lang=lang).lower() in categories]
+
+ if sections:
+ timeline = [p for p in timeline if p.section_name(lang).lower() in sections]
+
+ for post in timeline:
+ if tags:
+ cont = True
+ tags_lower = [t.lower() for t in post.tags]
+ for tag in tags:
+ if tag in tags_lower:
+ cont = False
+
+ if cont:
+ continue
+
+ filtered_timeline.append(post)
+
+ if sort:
+ filtered_timeline = natsort.natsorted(filtered_timeline, key=lambda post: post.meta[lang][sort], alg=natsort.ns.F | natsort.ns.IC)
+
+ if date:
+ filtered_timeline = [p for p in filtered_timeline if date_in_range(date, p.date)]
+
+ for post in filtered_timeline[start:stop:step]:
+ if slugs:
+ cont = True
+ for slug in slugs:
+ if slug == post.meta('slug'):
+ cont = False
+
+ if cont:
+ continue
+
+ bp = post.translated_base_path(lang)
+ if os.path.exists(bp) and state:
+ state.document.settings.record_dependencies.add(bp)
+ elif os.path.exists(bp) and self_post:
+ self_post.register_depfile(bp, lang=lang)
+
+ posts += [post]
+
+ if not posts:
+ return '', []
+
+ template_deps = site.template_system.template_deps(template)
+ if state:
+ # Register template as a dependency (Issue #2391)
+ for d in template_deps:
+ state.document.settings.record_dependencies.add(d)
+ elif self_post:
+ for d in template_deps:
+ self_post.register_depfile(d, lang=lang)
+
+ template_data = {
+ 'lang': lang,
+ 'posts': posts,
+ # Need to provide str, not TranslatableSetting (Issue #2104)
+ 'date_format': site.GLOBAL_CONTEXT.get('date_format')[lang],
+ 'post_list_id': post_list_id,
+ 'messages': site.MESSAGES,
+ }
+ output = site.template_system.render_template(
+ template, None, template_data)
+ return output, template_deps
- template_data = {
- 'lang': lang,
- 'posts': posts,
- # Need to provide str, not TranslatableSetting (Issue #2104)
- 'date_format': self.site.GLOBAL_CONTEXT.get('date_format')[lang],
- 'post_list_id': post_list_id,
- 'messages': self.site.MESSAGES,
- }
- output = self.site.template_system.render_template(
- template, None, template_data)
- return [nodes.raw('', output, format='html')]
+# Request file name from shortcode (Issue #2412)
+_do_post_list.nikola_shortcode_pass_filename = True
diff --git a/nikola/plugins/compile/rest/slides.py b/nikola/plugins/compile/rest/slides.py
index eb2cc97..7c5b34b 100644
--- a/nikola/plugins/compile/rest/slides.py
+++ b/nikola/plugins/compile/rest/slides.py
@@ -1,6 +1,6 @@
# -*- coding: utf-8 -*-
-# Copyright © 2012-2015 Roberto Alsina and others.
+# Copyright © 2012-2016 Roberto Alsina and others.
# Permission is hereby granted, free of charge, to any
# person obtaining a copy of this software and associated
diff --git a/nikola/plugins/compile/rest/soundcloud.py b/nikola/plugins/compile/rest/soundcloud.py
index 2577ff1..9fabe70 100644
--- a/nikola/plugins/compile/rest/soundcloud.py
+++ b/nikola/plugins/compile/rest/soundcloud.py
@@ -4,7 +4,7 @@
from docutils import nodes
from docutils.parsers.rst import Directive, directives
-
+from nikola.plugins.compile.rest import _align_choice, _align_options_base
from nikola.plugin_categories import RestExtension
@@ -22,11 +22,13 @@ class Plugin(RestExtension):
return super(Plugin, self).set_site(site)
-CODE = ("""<iframe width="{width}" height="{height}"
+CODE = """\
+<div class="soundcloud-player{align}">
+<iframe width="{width}" height="{height}"
scrolling="no" frameborder="no"
-src="https://w.soundcloud.com/player/?url=http://api.soundcloud.com/{preslug}/"""
- """{sid}">
-</iframe>""")
+src="https://w.soundcloud.com/player/?url=http://api.soundcloud.com/{preslug}/{sid}">
+</iframe>
+</div>"""
class SoundCloud(Directive):
@@ -44,6 +46,7 @@ class SoundCloud(Directive):
option_spec = {
'width': directives.positive_int,
'height': directives.positive_int,
+ "align": _align_choice
}
preslug = "tracks"
@@ -57,6 +60,10 @@ class SoundCloud(Directive):
'preslug': self.preslug,
}
options.update(self.options)
+ if self.options.get('align') in _align_options_base:
+ options['align'] = ' align-' + self.options['align']
+ else:
+ options['align'] = ''
return [nodes.raw('', CODE.format(**options), format='html')]
def check_content(self):
diff --git a/nikola/plugins/compile/rest/thumbnail.py b/nikola/plugins/compile/rest/thumbnail.py
index c24134a..37e0973 100644
--- a/nikola/plugins/compile/rest/thumbnail.py
+++ b/nikola/plugins/compile/rest/thumbnail.py
@@ -1,6 +1,6 @@
# -*- coding: utf-8 -*-
-# Copyright © 2014-2015 Pelle Nilsson and others.
+# Copyright © 2014-2016 Pelle Nilsson and others.
# Permission is hereby granted, free of charge, to any
# person obtaining a copy of this software and associated
diff --git a/nikola/plugins/compile/rest/vimeo.py b/nikola/plugins/compile/rest/vimeo.py
index 29ce5c1..f1ac6c3 100644
--- a/nikola/plugins/compile/rest/vimeo.py
+++ b/nikola/plugins/compile/rest/vimeo.py
@@ -1,6 +1,6 @@
# -*- coding: utf-8 -*-
-# Copyright © 2012-2015 Roberto Alsina and others.
+# Copyright © 2012-2016 Roberto Alsina and others.
# Permission is hereby granted, free of charge, to any
# person obtaining a copy of this software and associated
@@ -28,6 +28,7 @@
from docutils import nodes
from docutils.parsers.rst import Directive, directives
+from nikola.plugins.compile.rest import _align_choice, _align_options_base
import requests
import json
@@ -48,10 +49,12 @@ class Plugin(RestExtension):
return super(Plugin, self).set_site(site)
-CODE = """<iframe src="//player.vimeo.com/video/{vimeo_id}"
+CODE = """<div class="vimeo-video{align}">
+<iframe src="https://player.vimeo.com/video/{vimeo_id}"
width="{width}" height="{height}"
frameborder="0" webkitAllowFullScreen="webkitAllowFullScreen" mozallowfullscreen="mozallowfullscreen" allowFullScreen="allowFullScreen">
</iframe>
+</div>
"""
VIDEO_DEFAULT_HEIGHT = 500
@@ -73,6 +76,7 @@ class Vimeo(Directive):
option_spec = {
"width": directives.positive_int,
"height": directives.positive_int,
+ "align": _align_choice
}
# set to False for not querying the vimeo api for size
@@ -92,6 +96,10 @@ class Vimeo(Directive):
return err
self.set_video_size()
options.update(self.options)
+ if self.options.get('align') in _align_options_base:
+ options['align'] = ' align-' + self.options['align']
+ else:
+ options['align'] = ''
return [nodes.raw('', CODE.format(**options), format='html')]
def check_modules(self):
@@ -107,7 +115,7 @@ class Vimeo(Directive):
if json: # we can attempt to retrieve video attributes from vimeo
try:
- url = ('//vimeo.com/api/v2/video/{0}'
+ url = ('https://vimeo.com/api/v2/video/{0}'
'.json'.format(self.arguments[0]))
data = requests.get(url).text
video_attributes = json.loads(data)[0]
diff --git a/nikola/plugins/compile/rest/youtube.py b/nikola/plugins/compile/rest/youtube.py
index b3b84b0..b3dde62 100644
--- a/nikola/plugins/compile/rest/youtube.py
+++ b/nikola/plugins/compile/rest/youtube.py
@@ -1,6 +1,6 @@
# -*- coding: utf-8 -*-
-# Copyright © 2012-2015 Roberto Alsina and others.
+# Copyright © 2012-2016 Roberto Alsina and others.
# Permission is hereby granted, free of charge, to any
# person obtaining a copy of this software and associated
@@ -28,7 +28,7 @@
from docutils import nodes
from docutils.parsers.rst import Directive, directives
-
+from nikola.plugins.compile.rest import _align_choice, _align_options_base
from nikola.plugin_categories import RestExtension
@@ -46,10 +46,11 @@ class Plugin(RestExtension):
CODE = """\
-<iframe width="{width}"
-height="{height}"
-src="//www.youtube.com/embed/{yid}?rel=0&amp;hd=1&amp;wmode=transparent"
-></iframe>"""
+<div class="youtube-video{align}">
+<iframe width="{width}" height="{height}"
+src="https://www.youtube.com/embed/{yid}?rel=0&amp;hd=1&amp;wmode=transparent"
+></iframe>
+</div>"""
class Youtube(Directive):
@@ -67,6 +68,7 @@ class Youtube(Directive):
option_spec = {
"width": directives.positive_int,
"height": directives.positive_int,
+ "align": _align_choice
}
def run(self):
@@ -78,6 +80,10 @@ class Youtube(Directive):
'height': 344,
}
options.update(self.options)
+ if self.options.get('align') in _align_options_base:
+ options['align'] = ' align-' + self.options['align']
+ else:
+ options['align'] = ''
return [nodes.raw('', CODE.format(**options), format='html')]
def check_content(self):