summaryrefslogtreecommitdiffstats
path: root/nikola/plugins
diff options
context:
space:
mode:
authorLibravatarAgustin Henze <tin@sluc.org.ar>2014-02-28 08:49:38 -0300
committerLibravatarAgustin Henze <tin@sluc.org.ar>2014-02-28 08:49:38 -0300
commit2828399ba5cbb14502b023d4de1ba02f13dd5055 (patch)
tree38012b6bacaa508ca56fb6f4ba87b912bb54b8c9 /nikola/plugins
parentca94afc07df55cb7fc6fe3b4f3011877b7881195 (diff)
Imported Upstream version 6.3.0upstream/6.3.0
Diffstat (limited to 'nikola/plugins')
-rw-r--r--nikola/plugins/basic_import.py2
-rw-r--r--nikola/plugins/command/__init__.py2
-rw-r--r--nikola/plugins/command/auto.py49
-rw-r--r--nikola/plugins/command/bootswatch_theme.py2
-rw-r--r--nikola/plugins/command/check.py53
-rw-r--r--nikola/plugins/command/console.plugin2
-rw-r--r--nikola/plugins/command/console.py32
-rw-r--r--nikola/plugins/command/deploy.py15
-rw-r--r--nikola/plugins/command/import_blogger.py2
-rw-r--r--nikola/plugins/command/import_feed.py2
-rw-r--r--nikola/plugins/command/import_wordpress.py4
-rw-r--r--nikola/plugins/command/init.py2
-rw-r--r--nikola/plugins/command/install_plugin.py12
-rw-r--r--nikola/plugins/command/install_theme.py45
-rw-r--r--nikola/plugins/command/mincss.py2
-rw-r--r--nikola/plugins/command/new_post.py2
-rw-r--r--nikola/plugins/command/orphans.plugin10
-rw-r--r--nikola/plugins/command/orphans.py45
-rw-r--r--nikola/plugins/command/planetoid/__init__.py2
-rw-r--r--nikola/plugins/command/serve.py2
-rw-r--r--nikola/plugins/command/version.py4
-rw-r--r--nikola/plugins/compile/__init__.py25
-rw-r--r--nikola/plugins/compile/asciidoc.py13
-rw-r--r--nikola/plugins/compile/bbcode.py11
-rw-r--r--nikola/plugins/compile/html.py27
-rw-r--r--nikola/plugins/compile/ipynb/__init__.py23
-rw-r--r--nikola/plugins/compile/markdown/__init__.py14
-rw-r--r--nikola/plugins/compile/markdown/mdx_gist.py2
-rw-r--r--nikola/plugins/compile/markdown/mdx_nikola.py6
-rw-r--r--nikola/plugins/compile/markdown/mdx_podcast.py2
-rw-r--r--nikola/plugins/compile/misaka.py13
-rw-r--r--nikola/plugins/compile/pandoc.py12
-rw-r--r--nikola/plugins/compile/php.py12
-rw-r--r--nikola/plugins/compile/rest/__init__.py34
-rw-r--r--nikola/plugins/compile/rest/chart.py2
-rw-r--r--nikola/plugins/compile/rest/doc.py2
-rw-r--r--nikola/plugins/compile/rest/listing.py2
-rw-r--r--nikola/plugins/compile/rest/media.py2
-rw-r--r--nikola/plugins/compile/rest/post_list.py5
-rw-r--r--nikola/plugins/compile/rest/slides.py2
-rw-r--r--nikola/plugins/compile/rest/soundcloud.py9
-rw-r--r--nikola/plugins/compile/rest/template.txt8
-rw-r--r--nikola/plugins/compile/rest/vimeo.py2
-rw-r--r--nikola/plugins/compile/rest/youtube.py2
-rw-r--r--nikola/plugins/compile/textile.py13
-rw-r--r--nikola/plugins/compile/txt2tags.py15
-rw-r--r--nikola/plugins/compile/wiki.py13
-rw-r--r--nikola/plugins/loghandler/__init__.py25
-rw-r--r--nikola/plugins/loghandler/smtp.py2
-rw-r--r--nikola/plugins/loghandler/stderr.py6
-rw-r--r--nikola/plugins/task/__init__.py25
-rw-r--r--nikola/plugins/task/archive.py9
-rw-r--r--nikola/plugins/task/build_less.py13
-rw-r--r--nikola/plugins/task/build_sass.py15
-rw-r--r--nikola/plugins/task/bundles.py8
-rw-r--r--nikola/plugins/task/copy_assets.py2
-rw-r--r--nikola/plugins/task/copy_files.py2
-rw-r--r--nikola/plugins/task/galleries.py40
-rw-r--r--nikola/plugins/task/gzip.py2
-rw-r--r--nikola/plugins/task/indexes.py15
-rw-r--r--nikola/plugins/task/listings.py2
-rw-r--r--nikola/plugins/task/localsearch/__init__.py2
-rw-r--r--nikola/plugins/task/mustache/__init__.py8
-rw-r--r--nikola/plugins/task/pages.py2
-rw-r--r--nikola/plugins/task/posts.py2
-rw-r--r--nikola/plugins/task/redirect.py2
-rw-r--r--nikola/plugins/task/rss.py2
-rw-r--r--nikola/plugins/task/sitemap/__init__.py2
-rw-r--r--nikola/plugins/task/sources.py4
-rw-r--r--nikola/plugins/task/tags.py13
-rw-r--r--nikola/plugins/template/__init__.py25
-rw-r--r--nikola/plugins/template/jinja.py9
-rw-r--r--nikola/plugins/template/mako.py2
73 files changed, 582 insertions, 219 deletions
diff --git a/nikola/plugins/basic_import.py b/nikola/plugins/basic_import.py
index e368fca..0d94d16 100644
--- a/nikola/plugins/basic_import.py
+++ b/nikola/plugins/basic_import.py
@@ -1,6 +1,6 @@
# -*- coding: utf-8 -*-
-# Copyright © 2012-2013 Roberto Alsina and others.
+# Copyright © 2012-2014 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/command/__init__.py b/nikola/plugins/command/__init__.py
index 9be4d63..6ad8bac 100644
--- a/nikola/plugins/command/__init__.py
+++ b/nikola/plugins/command/__init__.py
@@ -1,6 +1,6 @@
# -*- coding: utf-8 -*-
-# Copyright © 2012-2013 Roberto Alsina and others.
+# Copyright © 2012-2014 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/command/auto.py b/nikola/plugins/command/auto.py
index cb726d9..01116d1 100644
--- a/nikola/plugins/command/auto.py
+++ b/nikola/plugins/command/auto.py
@@ -1,6 +1,6 @@
# -*- coding: utf-8 -*-
-# Copyright © 2012-2013 Roberto Alsina and others.
+# Copyright © 2012-2014 Roberto Alsina and others.
# Permission is hereby granted, free of charge, to any
# person obtaining a copy of this software and associated
@@ -26,30 +26,13 @@
from __future__ import print_function, unicode_literals
-import codecs
-import json
import os
import subprocess
+import webbrowser
from nikola.plugin_categories import Command
from nikola.utils import req_missing
-GUARDFILE = """#!/usr/bin/env python
-# -*- coding: utf-8 -*-
-from livereload.task import Task
-import json
-import subprocess
-
-def f():
- import subprocess
- subprocess.call(("nikola", "build"))
-
-fdata = json.loads('''{0}''')
-
-for watch in fdata:
- Task.add(watch, f)
-"""
-
class Auto(Command):
"""Start debugging console."""
@@ -76,9 +59,9 @@ class Auto(Command):
def _execute(self, options, args):
"""Start the watcher."""
try:
- from livereload.server import start
+ from livereload import Server
except ImportError:
- req_missing(['livereload'], 'use the "auto" command')
+ req_missing(['livereload>=2.0.0'], 'use the "auto" command')
return
# Run an initial build so we are uptodate
@@ -86,18 +69,18 @@ class Auto(Command):
port = options and options.get('port')
- # Create a Guardfile
- with codecs.open("Guardfile", "wb+", "utf8") as guardfile:
- l = ["conf.py", "themes", "templates", self.site.config['GALLERY_PATH']]
- for item in self.site.config['post_pages']:
- l.append(os.path.dirname(item[0]))
- for item in self.site.config['FILES_FOLDERS']:
- l.append(os.path.dirname(item))
- data = GUARDFILE.format(json.dumps(l))
- guardfile.write(data)
+ server = Server()
+ server.watch('conf.py')
+ server.watch('themes/')
+ server.watch('templates/')
+ server.watch(self.site.config['GALLERY_PATH'])
+ for item in self.site.config['post_pages']:
+ server.watch(os.path.dirname(item[0]))
+ for item in self.site.config['FILES_FOLDERS']:
+ server.watch(os.path.dirname(item))
out_folder = self.site.config['OUTPUT_FOLDER']
+ if options and options.get('browser'):
+ webbrowser.open('http://localhost:{0}'.format(port))
- os.chmod("Guardfile", 0o755)
-
- start(port, out_folder, options and options.get('browser'))
+ server.serve(port, out_folder)
diff --git a/nikola/plugins/command/bootswatch_theme.py b/nikola/plugins/command/bootswatch_theme.py
index eb27f94..94f37f2 100644
--- a/nikola/plugins/command/bootswatch_theme.py
+++ b/nikola/plugins/command/bootswatch_theme.py
@@ -1,6 +1,6 @@
# -*- coding: utf-8 -*-
-# Copyright © 2012-2013 Roberto Alsina and others.
+# Copyright © 2012-2014 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/command/check.py b/nikola/plugins/command/check.py
index 5c7e49a..a7e8c13 100644
--- a/nikola/plugins/command/check.py
+++ b/nikola/plugins/command/check.py
@@ -1,6 +1,6 @@
# -*- coding: utf-8 -*-
-# Copyright © 2012-2013 Roberto Alsina and others.
+# Copyright © 2012-2014 Roberto Alsina and others.
# Permission is hereby granted, free of charge, to any
# person obtaining a copy of this software and associated
@@ -40,6 +40,29 @@ from nikola.plugin_categories import Command
from nikola.utils import get_logger
+def real_scan_files(site):
+ task_fnames = set([])
+ real_fnames = set([])
+ output_folder = site.config['OUTPUT_FOLDER']
+ # First check that all targets are generated in the right places
+ for task in os.popen('nikola list --all', 'r').readlines():
+ task = task.strip()
+ if output_folder in task and ':' in task:
+ fname = task.split(':', 1)[-1]
+ task_fnames.add(fname)
+ # And now check that there are no non-target files
+ for root, dirs, files in os.walk(output_folder):
+ for src_name in files:
+ fname = os.path.join(root, src_name)
+ real_fnames.add(fname)
+
+ only_on_output = list(real_fnames - task_fnames)
+
+ only_on_input = list(task_fnames - real_fnames)
+
+ return (only_on_output, only_on_input)
+
+
class CommandCheck(Command):
"""Check the generated site."""
@@ -63,7 +86,7 @@ class CommandCheck(Command):
'long': 'check-files',
'type': bool,
'default': False,
- 'help': 'Check for unknown files',
+ 'help': 'Check for unknown (orphaned and not generated) files',
},
{
'name': 'clean',
@@ -154,7 +177,7 @@ class CommandCheck(Command):
failure = False
self.logger.notice("Checking Files:")
self.logger.notice("===============\n")
- only_on_output, only_on_input = self.real_scan_files()
+ only_on_output, only_on_input = real_scan_files(self.site)
# Ignore folders
only_on_output = [p for p in only_on_output if not os.path.isdir(p)]
@@ -162,7 +185,7 @@ class CommandCheck(Command):
if only_on_output:
only_on_output.sort()
- self.logger.warn("Files from unknown origins:")
+ self.logger.warn("Files from unknown origins (orphans):")
for f in only_on_output:
self.logger.warn(f)
failure = True
@@ -180,25 +203,3 @@ class CommandCheck(Command):
for f in only_on_output:
os.unlink(f)
return True
-
- def real_scan_files(self):
- task_fnames = set([])
- real_fnames = set([])
- output_folder = self.site.config['OUTPUT_FOLDER']
- # First check that all targets are generated in the right places
- for task in os.popen('nikola list --all', 'r').readlines():
- task = task.strip()
- if output_folder in task and ':' in task:
- fname = task.split(':', 1)[-1]
- task_fnames.add(fname)
- # And now check that there are no non-target files
- for root, dirs, files in os.walk(output_folder):
- for src_name in files:
- fname = os.path.join(root, src_name)
- real_fnames.add(fname)
-
- only_on_output = list(real_fnames - task_fnames)
-
- only_on_input = list(task_fnames - real_fnames)
-
- return (only_on_output, only_on_input)
diff --git a/nikola/plugins/command/console.plugin b/nikola/plugins/command/console.plugin
index a2be9ca..2eeedae 100644
--- a/nikola/plugins/command/console.plugin
+++ b/nikola/plugins/command/console.plugin
@@ -3,7 +3,7 @@ Name = console
Module = console
[Documentation]
-Author = Roberto Alsina
+Author = Chris Warrick, Roberto Alsina
Version = 0.1
Website = http://getnikola.com
Description = Start a debugging python console
diff --git a/nikola/plugins/command/console.py b/nikola/plugins/command/console.py
index fe17dfc..e66b650 100644
--- a/nikola/plugins/command/console.py
+++ b/nikola/plugins/command/console.py
@@ -1,6 +1,6 @@
# -*- coding: utf-8 -*-
-# Copyright © 2012-2013 Roberto Alsina and others.
+# Copyright © 2012-2014 Chris Warrick, Roberto Alsina and others.
# Permission is hereby granted, free of charge, to any
# person obtaining a copy of this software and associated
@@ -39,8 +39,21 @@ class Console(Command):
"""Start debugging console."""
name = "console"
shells = ['ipython', 'bpython', 'plain']
- doc_purpose = "Start an interactive Python (IPython->bpython->plain) console with access to your site and configuration"
+ doc_purpose = "start an interactive Python console with access to your site"
+ doc_description = """\
+Order of resolution: IPython → bpython [deprecated] → plain Python interpreter
+The site engine is accessible as `SITE`, and the config as `conf`."""
header = "Nikola v" + __version__ + " -- {0} Console (conf = configuration, SITE = site engine)"
+ cmd_options = [
+ {
+ 'name': 'plain',
+ 'short': 'p',
+ 'long': 'plain',
+ 'type': bool,
+ 'default': False,
+ 'help': 'Force the plain Python console',
+ }
+ ]
def ipython(self):
"""IPython shell."""
@@ -102,9 +115,12 @@ class Console(Command):
def _execute(self, options, args):
"""Start the console."""
- for shell in self.shells:
- try:
- return getattr(self, shell)()
- except ImportError:
- pass
- raise ImportError
+ if options['plain']:
+ self.plain()
+ else:
+ for shell in self.shells:
+ try:
+ return getattr(self, shell)()
+ except ImportError:
+ pass
+ raise ImportError
diff --git a/nikola/plugins/command/deploy.py b/nikola/plugins/command/deploy.py
index efb909d..eb5787e 100644
--- a/nikola/plugins/command/deploy.py
+++ b/nikola/plugins/command/deploy.py
@@ -1,6 +1,6 @@
# -*- coding: utf-8 -*-
-# Copyright © 2012-2013 Roberto Alsina and others.
+# Copyright © 2012-2014 Roberto Alsina and others.
# Permission is hereby granted, free of charge, to any
# person obtaining a copy of this software and associated
@@ -85,18 +85,17 @@ class Deploy(Command):
sys.exit(e.returncode)
self.logger.notice("Successful deployment")
- if self.site.config['TIMEZONE'] is not None:
- tzinfo = pytz.timezone(self.site.config['TIMEZONE'])
- else:
- tzinfo = pytz.UTC
+ tzinfo = pytz.timezone(self.site.config['TIMEZONE'])
try:
with open(timestamp_path, 'rb') as inf:
last_deploy = literal_eval(inf.read().strip())
- # this might ignore DST
- last_deploy = last_deploy.replace(tzinfo=tzinfo)
+ if tzinfo:
+ last_deploy = last_deploy.replace(tzinfo=tzinfo)
clean = False
except Exception:
- last_deploy = datetime(1970, 1, 1).replace(tzinfo=tzinfo)
+ last_deploy = datetime(1970, 1, 1)
+ if tzinfo:
+ last_deploy = last_deploy.replace(tzinfo=tzinfo)
clean = True
new_deploy = datetime.now()
diff --git a/nikola/plugins/command/import_blogger.py b/nikola/plugins/command/import_blogger.py
index 53618b4..ea12b4a 100644
--- a/nikola/plugins/command/import_blogger.py
+++ b/nikola/plugins/command/import_blogger.py
@@ -1,6 +1,6 @@
# -*- coding: utf-8 -*-
-# Copyright © 2012-2013 Roberto Alsina and others.
+# Copyright © 2012-2014 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/command/import_feed.py b/nikola/plugins/command/import_feed.py
index b25d9ec..70a5cd5 100644
--- a/nikola/plugins/command/import_feed.py
+++ b/nikola/plugins/command/import_feed.py
@@ -1,6 +1,6 @@
# -*- coding: utf-8 -*-
-# Copyright © 2012-2013 Roberto Alsina and others.
+# Copyright © 2012-2014 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/command/import_wordpress.py b/nikola/plugins/command/import_wordpress.py
index 4f32198..0c9915a 100644
--- a/nikola/plugins/command/import_wordpress.py
+++ b/nikola/plugins/command/import_wordpress.py
@@ -1,6 +1,6 @@
# -*- coding: utf-8 -*-
-# Copyright © 2012-2013 Roberto Alsina and others.
+# Copyright © 2012-2014 Roberto Alsina and others.
# Permission is hereby granted, free of charge, to any
# person obtaining a copy of this software and associated
@@ -145,7 +145,7 @@ class CommandImportWordpress(Command, ImportMixin):
rendered_template = re.sub('# REDIRECTIONS = ', 'REDIRECTIONS = ',
rendered_template)
if self.timezone:
- rendered_template = re.sub('# TIMEZONE = \'Europe/Zurich\'',
+ rendered_template = re.sub('# TIMEZONE = \'UTC\'',
'TIMEZONE = \'' + self.timezone + '\'',
rendered_template)
self.write_configuration(self.get_configuration_output_path(),
diff --git a/nikola/plugins/command/init.py b/nikola/plugins/command/init.py
index 1873ec4..96caad8 100644
--- a/nikola/plugins/command/init.py
+++ b/nikola/plugins/command/init.py
@@ -1,6 +1,6 @@
# -*- coding: utf-8 -*-
-# Copyright © 2012-2013 Roberto Alsina and others.
+# Copyright © 2012-2014 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/command/install_plugin.py b/nikola/plugins/command/install_plugin.py
index fdbd0b7..1d6584d 100644
--- a/nikola/plugins/command/install_plugin.py
+++ b/nikola/plugins/command/install_plugin.py
@@ -1,6 +1,6 @@
# -*- coding: utf-8 -*-
-# Copyright © 2012-2013 Roberto Alsina and others.
+# Copyright © 2012-2014 Roberto Alsina and others.
# Permission is hereby granted, free of charge, to any
# person obtaining a copy of this software and associated
@@ -27,6 +27,7 @@
from __future__ import print_function
import codecs
import os
+import sys
import json
import shutil
import subprocess
@@ -145,7 +146,6 @@ class CommandInstallPlugin(Command):
shutil.copytree(plugin_path, dest_path)
reqpath = os.path.join(dest_path, 'requirements.txt')
- print(reqpath)
if os.path.exists(reqpath):
LOGGER.notice('This plugin has Python dependencies.')
LOGGER.notice('Installing dependencies with pip...')
@@ -180,6 +180,10 @@ class CommandInstallPlugin(Command):
LOGGER.notice('This plugin has a sample config file.')
print('Contents of the conf.py.sample file:\n')
with codecs.open(confpypath, 'rb', 'utf-8') as fh:
- print(indent(pygments.highlight(
- fh.read(), PythonLexer(), TerminalFormatter()), 4 * ' '))
+ if sys.platform == 'win32':
+ print(indent(pygments.highlight(
+ fh.read(), PythonLexer(), TerminalFormatter()),
+ 4 * ' '))
+ else:
+ print(indent(fh.read(), 4 * ' '))
return True
diff --git a/nikola/plugins/command/install_theme.py b/nikola/plugins/command/install_theme.py
index a9d835a..569397b 100644
--- a/nikola/plugins/command/install_theme.py
+++ b/nikola/plugins/command/install_theme.py
@@ -1,6 +1,6 @@
# -*- coding: utf-8 -*-
-# Copyright © 2012-2013 Roberto Alsina and others.
+# Copyright © 2012-2014 Roberto Alsina and others.
# Permission is hereby granted, free of charge, to any
# person obtaining a copy of this software and associated
@@ -26,9 +26,10 @@
from __future__ import print_function
import os
+import sys
+import codecs
import json
import shutil
-import codecs
from io import BytesIO
import pygments
@@ -116,18 +117,22 @@ class CommandInstallTheme(Command):
print(theme)
return True
else:
- self.do_install(name, data)
- # See if the theme's parent is available. If not, install it
- while True:
- parent_name = utils.get_parent_theme_name(name)
- if parent_name is None:
- break
- try:
- utils.get_theme_path(parent_name)
- break
- except: # Not available
- self.do_install(parent_name, data)
- name = parent_name
+ # `name` may be modified by the while loop.
+ origname = name
+ installstatus = self.do_install(name, data)
+ # See if the theme's parent is available. If not, install it
+ while True:
+ parent_name = utils.get_parent_theme_name(name)
+ if parent_name is None:
+ break
+ try:
+ utils.get_theme_path(parent_name)
+ break
+ except: # Not available
+ self.do_install(parent_name, data)
+ name = parent_name
+ if installstatus:
+ LOGGER.notice('Remember to set THEME="{0}" in conf.py to use this theme.'.format(origname))
def do_install(self, name, data):
if name in data:
@@ -155,9 +160,13 @@ class CommandInstallTheme(Command):
shutil.copytree(theme_path, dest_path)
confpypath = os.path.join(dest_path, 'conf.py.sample')
if os.path.exists(confpypath):
- LOGGER.notice('This plugin has a sample config file.')
+ LOGGER.notice('This plugin has a sample config file. Integrate it with yours in order to make this theme work!')
print('Contents of the conf.py.sample file:\n')
with codecs.open(confpypath, 'rb', 'utf-8') as fh:
- print(indent(pygments.highlight(
- fh.read(), PythonLexer(), TerminalFormatter()), 4 * ' '))
- return True
+ if sys.platform == 'win32':
+ print(indent(pygments.highlight(
+ fh.read(), PythonLexer(), TerminalFormatter()),
+ 4 * ' '))
+ else:
+ print(indent(fh.read(), 4 * ' '))
+ return True
diff --git a/nikola/plugins/command/mincss.py b/nikola/plugins/command/mincss.py
index 5c9a7cb..0193458 100644
--- a/nikola/plugins/command/mincss.py
+++ b/nikola/plugins/command/mincss.py
@@ -1,6 +1,6 @@
# -*- coding: utf-8 -*-
-# Copyright © 2012-2013 Roberto Alsina and others.
+# Copyright © 2012-2014 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/command/new_post.py b/nikola/plugins/command/new_post.py
index ea0f3de..a5c551d 100644
--- a/nikola/plugins/command/new_post.py
+++ b/nikola/plugins/command/new_post.py
@@ -1,6 +1,6 @@
# -*- coding: utf-8 -*-
-# Copyright © 2012-2013 Roberto Alsina and others.
+# Copyright © 2012-2014 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/command/orphans.plugin b/nikola/plugins/command/orphans.plugin
new file mode 100644
index 0000000..408578b
--- /dev/null
+++ b/nikola/plugins/command/orphans.plugin
@@ -0,0 +1,10 @@
+[Core]
+Name = orphans
+Module = orphans
+
+[Documentation]
+Author = Roberto Alsina, Chris Warrick
+Version = 0.1
+Website = http://getnikola.com
+Description = List all orphans
+
diff --git a/nikola/plugins/command/orphans.py b/nikola/plugins/command/orphans.py
new file mode 100644
index 0000000..ff114b4
--- /dev/null
+++ b/nikola/plugins/command/orphans.py
@@ -0,0 +1,45 @@
+# -*- coding: utf-8 -*-
+
+# Copyright © 2012-2014 Roberto Alsina, Chris Warrick and others.
+
+# 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 __future__ import print_function
+import os
+
+from nikola.plugin_categories import Command
+from nikola.plugins.command.check import real_scan_files
+
+
+class CommandOrphans(Command):
+ name = "orphans"
+ doc_purpose = "list all orphans"
+ doc_description = """\
+List all orphans, i.e. all files that are in the output directory,
+but are not generated by Nikola.
+
+Output contains filenames only (it is passable to `xargs rm` or the like)."""
+
+ def _execute(self, options, args):
+ orphans = real_scan_files(self.site)[0]
+ print('\n'.join([p for p in orphans if not os.path.isdir(p)]))
diff --git a/nikola/plugins/command/planetoid/__init__.py b/nikola/plugins/command/planetoid/__init__.py
index 369862b..ff5dd13 100644
--- a/nikola/plugins/command/planetoid/__init__.py
+++ b/nikola/plugins/command/planetoid/__init__.py
@@ -1,6 +1,6 @@
# -*- coding: utf-8 -*-
-# Copyright © 2012-2013 Roberto Alsina and others.
+# Copyright © 2012-2014 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/command/serve.py b/nikola/plugins/command/serve.py
index 07403d4..2dd15c1 100644
--- a/nikola/plugins/command/serve.py
+++ b/nikola/plugins/command/serve.py
@@ -1,6 +1,6 @@
# -*- coding: utf-8 -*-
-# Copyright © 2012-2013 Roberto Alsina and others.
+# Copyright © 2012-2014 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/command/version.py b/nikola/plugins/command/version.py
index 65896e9..9b42423 100644
--- a/nikola/plugins/command/version.py
+++ b/nikola/plugins/command/version.py
@@ -1,6 +1,6 @@
# -*- coding: utf-8 -*-
-# Copyright © 2012-2013 Roberto Alsina and others.
+# Copyright © 2012-2014 Roberto Alsina and others.
# Permission is hereby granted, free of charge, to any
# person obtaining a copy of this software and associated
@@ -41,4 +41,4 @@ class CommandVersion(Command):
def _execute(self, options={}, args=None):
"""Print the version number."""
- print("Nikola version " + __version__)
+ print("Nikola v" + __version__)
diff --git a/nikola/plugins/compile/__init__.py b/nikola/plugins/compile/__init__.py
index e69de29..6ad8bac 100644
--- a/nikola/plugins/compile/__init__.py
+++ b/nikola/plugins/compile/__init__.py
@@ -0,0 +1,25 @@
+# -*- coding: utf-8 -*-
+
+# Copyright © 2012-2014 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 "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.
diff --git a/nikola/plugins/compile/asciidoc.py b/nikola/plugins/compile/asciidoc.py
index 67dfe1a..12cb4bf 100644
--- a/nikola/plugins/compile/asciidoc.py
+++ b/nikola/plugins/compile/asciidoc.py
@@ -1,6 +1,6 @@
# -*- coding: utf-8 -*-
-# Copyright © 2012-2013 Roberto Alsina and others.
+# Copyright © 2012-2014 Roberto Alsina and others.
# Permission is hereby granted, free of charge, to any
# person obtaining a copy of this software and associated
@@ -37,11 +37,17 @@ import subprocess
from nikola.plugin_categories import PageCompiler
from nikola.utils import makedirs, req_missing
+try:
+ from collections import OrderedDict
+except ImportError:
+ OrderedDict = None # NOQA
+
class CompileAsciiDoc(PageCompiler):
"""Compile asciidoc into HTML."""
name = "asciidoc"
+ demote_headers = True
def compile_html(self, source, dest, is_two_file=True):
makedirs(os.path.dirname(dest))
@@ -52,7 +58,10 @@ class CompileAsciiDoc(PageCompiler):
req_missing(['asciidoc'], 'build this site (compile with asciidoc)', python=False)
def create_post(self, path, onefile=False, **kw):
- metadata = {}
+ if OrderedDict is not None:
+ metadata = OrderedDict()
+ else:
+ metadata = {}
metadata.update(self.default_metadata)
metadata.update(kw)
makedirs(os.path.dirname(path))
diff --git a/nikola/plugins/compile/bbcode.py b/nikola/plugins/compile/bbcode.py
index e998417..5345be3 100644
--- a/nikola/plugins/compile/bbcode.py
+++ b/nikola/plugins/compile/bbcode.py
@@ -1,6 +1,6 @@
# -*- coding: utf-8 -*-
-# Copyright © 2012-2013 Roberto Alsina and others.
+# Copyright © 2012-2014 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,10 @@ except ImportError:
from nikola.plugin_categories import PageCompiler
from nikola.utils import makedirs, req_missing
+try:
+ from collections import OrderedDict
+except ImportError:
+ OrderedDict = None # NOQA
class CompileBbcode(PageCompiler):
@@ -63,7 +67,10 @@ class CompileBbcode(PageCompiler):
out_file.write(output)
def create_post(self, path, onefile=False, **kw):
- metadata = {}
+ if OrderedDict is not None:
+ metadata = OrderedDict()
+ else:
+ metadata = {}
metadata.update(self.default_metadata)
metadata.update(kw)
makedirs(os.path.dirname(path))
diff --git a/nikola/plugins/compile/html.py b/nikola/plugins/compile/html.py
index a309960..5352f00 100644
--- a/nikola/plugins/compile/html.py
+++ b/nikola/plugins/compile/html.py
@@ -1,6 +1,6 @@
# -*- coding: utf-8 -*-
-# Copyright © 2012-2013 Roberto Alsina and others.
+# Copyright © 2012-2014 Roberto Alsina and others.
# Permission is hereby granted, free of charge, to any
# person obtaining a copy of this software and associated
@@ -27,25 +27,40 @@
"""Implementation of compile_html for HTML source files."""
import os
-import shutil
+import re
import codecs
from nikola.plugin_categories import PageCompiler
from nikola.utils import makedirs
+try:
+ from collections import OrderedDict
+except ImportError:
+ OrderedDict = None # NOQA
+
+
+_META_SEPARATOR = '(' + os.linesep * 2 + '|' + ('\n' * 2) + '|' + ("\r\n" * 2) + ')'
+
class CompileHtml(PageCompiler):
"""Compile HTML into HTML."""
-
name = "html"
def compile_html(self, source, dest, is_two_file=True):
makedirs(os.path.dirname(dest))
- shutil.copyfile(source, dest)
+ with codecs.open(dest, "w+", "utf8") as out_file:
+ with codecs.open(source, "r", "utf8") as in_file:
+ data = in_file.read()
+ if not is_two_file:
+ data = re.split(_META_SEPARATOR, data, maxsplit=1)[-1]
+ out_file.write(data)
return True
def create_post(self, path, onefile=False, **kw):
- metadata = {}
+ if OrderedDict is not None:
+ metadata = OrderedDict()
+ else:
+ metadata = {}
metadata.update(self.default_metadata)
metadata.update(kw)
makedirs(os.path.dirname(path))
@@ -55,4 +70,4 @@ class CompileHtml(PageCompiler):
for k, v in metadata.items():
fd.write('.. {0}: {1}\n'.format(k, v))
fd.write('-->\n\n')
- fd.write("\n<p>Write your post here.</p>")
+ fd.write("\n<p>Write your post here.</p>\n")
diff --git a/nikola/plugins/compile/ipynb/__init__.py b/nikola/plugins/compile/ipynb/__init__.py
index 7c318ca..5f2f0b3 100644
--- a/nikola/plugins/compile/ipynb/__init__.py
+++ b/nikola/plugins/compile/ipynb/__init__.py
@@ -1,6 +1,6 @@
# -*- coding: utf-8 -*-
-# Copyright © 2013 Damian Avila.
+# Copyright © 2013-2014 Damián Avila and others.
# Permission is hereby granted, free of charge, to any
# person obtaining a copy of this software and associated
@@ -41,6 +41,11 @@ except ImportError:
from nikola.plugin_categories import PageCompiler
from nikola.utils import makedirs, req_missing
+try:
+ from collections import OrderedDict
+except ImportError:
+ OrderedDict = None # NOQA
+
class CompileIPynb(PageCompiler):
"""Compile IPynb into HTML."""
@@ -49,7 +54,7 @@ class CompileIPynb(PageCompiler):
def compile_html(self, source, dest, is_two_file=True):
if flag is None:
- req_missing(['ipython>=1.0.0'], 'build this site (compile ipynb)')
+ req_missing(['ipython>=1.1.0'], 'build this site (compile ipynb)')
makedirs(os.path.dirname(dest))
HTMLExporter.default_template = 'basic'
c = Config(self.site.config['IPYNB_CONFIG'])
@@ -62,18 +67,20 @@ class CompileIPynb(PageCompiler):
out_file.write(body)
def create_post(self, path, onefile=False, **kw):
- metadata = {}
+ if OrderedDict is not None:
+ metadata = OrderedDict()
+ else:
+ metadata = {}
metadata.update(self.default_metadata)
metadata.update(kw)
d_name = os.path.dirname(path)
makedirs(os.path.dirname(path))
meta_path = os.path.join(d_name, kw['slug'] + ".meta")
with codecs.open(meta_path, "wb+", "utf8") as fd:
- if onefile:
- fd.write('%s\n' % kw['title'])
- fd.write('%s\n' % kw['slug'])
- fd.write('%s\n' % kw['date'])
- fd.write('%s\n' % kw['tags'])
+ fd.write('\n'.join((metadata['title'], metadata['slug'],
+ metadata['date'], metadata['tags'],
+ metadata['link'],
+ metadata['description'], metadata['type'])))
print("Your post's metadata is at: ", meta_path)
with codecs.open(path, "wb+", "utf8") as fd:
fd.write("""{
diff --git a/nikola/plugins/compile/markdown/__init__.py b/nikola/plugins/compile/markdown/__init__.py
index b41c6b5..1376b11 100644
--- a/nikola/plugins/compile/markdown/__init__.py
+++ b/nikola/plugins/compile/markdown/__init__.py
@@ -1,6 +1,6 @@
# -*- coding: utf-8 -*-
-# Copyright © 2012-2013 Roberto Alsina and others.
+# Copyright © 2012-2014 Roberto Alsina and others.
# Permission is hereby granted, free of charge, to any
# person obtaining a copy of this software and associated
@@ -50,6 +50,12 @@ except ImportError:
gist_extension = None
podcast_extension = None
+
+try:
+ from collections import OrderedDict
+except ImportError:
+ OrderedDict = None # NOQA
+
from nikola.plugin_categories import PageCompiler
from nikola.utils import makedirs, req_missing
@@ -58,6 +64,7 @@ class CompileMarkdown(PageCompiler):
"""Compile markdown into HTML."""
name = "markdown"
+ demote_headers = True
extensions = [gist_extension, nikola_extension, podcast_extension]
site = None
@@ -75,7 +82,10 @@ class CompileMarkdown(PageCompiler):
out_file.write(output)
def create_post(self, path, onefile=False, **kw):
- metadata = {}
+ if OrderedDict is not None:
+ metadata = OrderedDict()
+ else:
+ metadata = {}
metadata.update(self.default_metadata)
metadata.update(kw)
makedirs(os.path.dirname(path))
diff --git a/nikola/plugins/compile/markdown/mdx_gist.py b/nikola/plugins/compile/markdown/mdx_gist.py
index 3c3bef9..d92295d 100644
--- a/nikola/plugins/compile/markdown/mdx_gist.py
+++ b/nikola/plugins/compile/markdown/mdx_gist.py
@@ -1,6 +1,6 @@
# -*- coding: utf-8 -*-
#
-# Copyright (c) 2013 Michael Rabbitt.
+# Copyright © 2013 Michael Rabbitt.
#
# 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/markdown/mdx_nikola.py b/nikola/plugins/compile/markdown/mdx_nikola.py
index b0ad2f7..b7c29a5 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-2013 Roberto Alsina and others.
+# Copyright © 2012-2014 Roberto Alsina and others.
# Permission is hereby granted, free of charge, to any
# person obtaining a copy of this software and associated
@@ -34,10 +34,6 @@ from markdown.extensions import Extension
class NikolaPostProcessor(Postprocessor):
def run(self, text):
output = text
- # h1 is reserved for the title so increment all header levels
- for n in reversed(range(1, 9)):
- output = re.sub('<h%i>' % n, '<h%i>' % (n + 1), output)
- output = re.sub('</h%i>' % n, '</h%i>' % (n + 1), output)
# python-markdown's highlighter uses the class 'codehilite' to wrap
# code, instead of the standard 'code'. None of the standard
diff --git a/nikola/plugins/compile/markdown/mdx_podcast.py b/nikola/plugins/compile/markdown/mdx_podcast.py
index be8bb6b..b38b969 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 (c) 2013 Michael Rabbitt, Roberto Alsina
+# Copyright © 2013-2014 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/misaka.py b/nikola/plugins/compile/misaka.py
index 3733a85..8777ffc 100644
--- a/nikola/plugins/compile/misaka.py
+++ b/nikola/plugins/compile/misaka.py
@@ -1,6 +1,6 @@
# -*- coding: utf-8 -*-
-# Copyright (c) 2013 Chris Lee
+# Copyright © 2013-2014 Chris Lee and others.
# Permission is hereby granted, free of charge, to any
# person obtaining a copy of this software and associated
@@ -37,6 +37,11 @@ try:
except ImportError:
misaka = None # NOQA
nikola_extension = None
+try:
+ from collections import OrderedDict
+except ImportError:
+ OrderedDict = None # NOQA
+
gist_extension = None
podcast_extension = None
@@ -48,6 +53,7 @@ class CompileMisaka(PageCompiler):
"""Compile Misaka into HTML."""
name = "misaka"
+ demote_headers = True
def __init__(self, *args, **kwargs):
super(CompileMisaka, self).__init__(*args, **kwargs)
@@ -68,7 +74,10 @@ class CompileMisaka(PageCompiler):
out_file.write(output)
def create_post(self, path, onefile=False, **kw):
- metadata = {}
+ if OrderedDict is not None:
+ metadata = OrderedDict()
+ else:
+ metadata = {}
metadata.update(self.default_metadata)
metadata.update(kw)
makedirs(os.path.dirname(path))
diff --git a/nikola/plugins/compile/pandoc.py b/nikola/plugins/compile/pandoc.py
index 3a2911f..57c7d71 100644
--- a/nikola/plugins/compile/pandoc.py
+++ b/nikola/plugins/compile/pandoc.py
@@ -1,6 +1,6 @@
# -*- coding: utf-8 -*-
-# Copyright © 2012-2013 Roberto Alsina and others.
+# Copyright © 2012-2014 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,11 @@ import subprocess
from nikola.plugin_categories import PageCompiler
from nikola.utils import req_missing, makedirs
+try:
+ from collections import OrderedDict
+except ImportError:
+ OrderedDict = None # NOQA
+
class CompilePandoc(PageCompiler):
"""Compile markups into HTML using pandoc."""
@@ -52,7 +57,10 @@ class CompilePandoc(PageCompiler):
req_missing(['pandoc'], 'build this site (compile with pandoc)', python=False)
def create_post(self, path, onefile=False, **kw):
- metadata = {}
+ if OrderedDict is not None:
+ metadata = OrderedDict()
+ else:
+ metadata = {}
metadata.update(self.default_metadata)
metadata.update(kw)
makedirs(os.path.dirname(path))
diff --git a/nikola/plugins/compile/php.py b/nikola/plugins/compile/php.py
index 44701c8..14b80e8 100644
--- a/nikola/plugins/compile/php.py
+++ b/nikola/plugins/compile/php.py
@@ -1,6 +1,6 @@
# -*- coding: utf-8 -*-
-# Copyright © 2012-2013 Roberto Alsina and others.
+# Copyright © 2012-2014 Roberto Alsina and others.
# Permission is hereby granted, free of charge, to any
# person obtaining a copy of this software and associated
@@ -35,6 +35,11 @@ import codecs
from nikola.plugin_categories import PageCompiler
from nikola.utils import makedirs
+try:
+ from collections import OrderedDict
+except ImportError:
+ OrderedDict = None # NOQA
+
class CompilePhp(PageCompiler):
"""Compile PHP into PHP."""
@@ -46,7 +51,10 @@ class CompilePhp(PageCompiler):
shutil.copyfile(source, dest)
def create_post(self, path, onefile=False, **kw):
- metadata = {}
+ if OrderedDict is not None:
+ metadata = OrderedDict()
+ else:
+ metadata = {}
metadata.update(self.default_metadata)
metadata.update(kw)
os.makedirs(os.path.dirname(path))
diff --git a/nikola/plugins/compile/rest/__init__.py b/nikola/plugins/compile/rest/__init__.py
index c71a5f8..50b37cf 100644
--- a/nikola/plugins/compile/rest/__init__.py
+++ b/nikola/plugins/compile/rest/__init__.py
@@ -1,6 +1,6 @@
# -*- coding: utf-8 -*-
-# Copyright © 2012-2013 Roberto Alsina and others.
+# Copyright © 2012-2014 Roberto Alsina and others.
# Permission is hereby granted, free of charge, to any
# person obtaining a copy of this software and associated
@@ -35,10 +35,16 @@ try:
import docutils.utils
import docutils.io
import docutils.readers.standalone
+ import docutils.writers.html4css1
has_docutils = True
except ImportError:
has_docutils = False
+try:
+ from collections import OrderedDict
+except ImportError:
+ OrderedDict = None # NOQA
+
from nikola.plugin_categories import PageCompiler
from nikola.utils import get_logger, makedirs, req_missing
@@ -47,6 +53,7 @@ class CompileRest(PageCompiler):
"""Compile reSt into HTML."""
name = "rest"
+ demote_headers = True
logger = None
def compile_html(self, source, dest, is_two_file=True):
@@ -71,14 +78,16 @@ class CompileRest(PageCompiler):
# author).
add_ln = len(spl[0].splitlines()) + 1
+ default_template_path = os.path.join(os.path.dirname(__file__), 'template.txt')
output, error_level, deps = rst2html(
data, settings_overrides={
- 'initial_header_level': 2,
+ '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, l_source=source, l_add_ln=add_ln)
out_file.write(output)
deps_path = dest + '.dep'
@@ -94,7 +103,10 @@ class CompileRest(PageCompiler):
return False
def create_post(self, path, onefile=False, **kw):
- metadata = {}
+ if OrderedDict is not None:
+ metadata = OrderedDict()
+ else:
+ metadata = {}
metadata.update(self.default_metadata)
metadata.update(kw)
makedirs(os.path.dirname(path))
@@ -117,6 +129,9 @@ class CompileRest(PageCompiler):
plugin_info.plugin_object.short_help = plugin_info.description
self.logger = get_logger('compile_rest', site.loghandlers)
+ if not site.debug:
+ self.logger.level = 4
+
return super(CompileRest, self).set_site(site)
@@ -139,7 +154,10 @@ def get_observer(settings):
"""
errormap = {0: 1, 1: 2, 2: 4, 3: 5, 4: 6}
text = docutils.nodes.Element.astext(msg)
- out = '[{source}:{line}] {text}'.format(source=settings['source'], line=msg['line'] + settings['add_ln'], text=text)
+ line = msg['line'] + settings['add_ln'] if 'line' in msg else 0
+ out = '[{source}{colon}{line}] {text}'.format(
+ source=settings['source'], colon=(':' if line else ''),
+ line=line, text=text)
settings['logger'].log(errormap[msg['level']], out)
return observer
@@ -155,6 +173,14 @@ class NikolaReader(docutils.readers.standalone.Reader):
return document
+def add_node(node, visit_function=None, depart_function=None):
+ docutils.nodes._add_node_class_names([node.__name__])
+ if visit_function:
+ setattr(docutils.writers.html4css1.HTMLTranslator, 'visit_' + node.__name__, visit_function)
+ if depart_function:
+ setattr(docutils.writers.html4css1.HTMLTranslator, 'depart_' + node.__name__, depart_function)
+
+
def rst2html(source, source_path=None, source_class=docutils.io.StringInput,
destination_path=None, reader=None,
parser=None, parser_name='restructuredtext', writer=None,
diff --git a/nikola/plugins/compile/rest/chart.py b/nikola/plugins/compile/rest/chart.py
index ee917b9..03878a3 100644
--- a/nikola/plugins/compile/rest/chart.py
+++ b/nikola/plugins/compile/rest/chart.py
@@ -1,6 +1,6 @@
# -*- coding: utf-8 -*-
-# Copyright © 2012-2013 Roberto Alsina and others.
+# Copyright © 2012-2014 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/doc.py b/nikola/plugins/compile/rest/doc.py
index 915a7e1..a150a81 100644
--- a/nikola/plugins/compile/rest/doc.py
+++ b/nikola/plugins/compile/rest/doc.py
@@ -1,6 +1,6 @@
# -*- coding: utf-8 -*-
-# Copyright © 2012-2013 Roberto Alsina and others.
+# Copyright © 2012-2014 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/listing.py b/nikola/plugins/compile/rest/listing.py
index 31975bb..ecf885f 100644
--- a/nikola/plugins/compile/rest/listing.py
+++ b/nikola/plugins/compile/rest/listing.py
@@ -1,6 +1,6 @@
# -*- coding: utf-8 -*-
-# Copyright © 2012-2013 Roberto Alsina and others.
+# Copyright © 2012-2014 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/media.py b/nikola/plugins/compile/rest/media.py
index d1930dd..ccda559 100644
--- a/nikola/plugins/compile/rest/media.py
+++ b/nikola/plugins/compile/rest/media.py
@@ -1,6 +1,6 @@
# -*- coding: utf-8 -*-
-# Copyright © 2012-2013 Roberto Alsina and others.
+# Copyright © 2012-2014 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/post_list.py b/nikola/plugins/compile/rest/post_list.py
index eae4016..6804b58 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 Udo Spallek, Roberto Alsina and others.
+# Copyright © 2013-2014 Udo Spallek, Roberto Alsina and others.
# Permission is hereby granted, free of charge, to any
# person obtaining a copy of this software and associated
@@ -33,6 +33,9 @@ from docutils.parsers.rst import Directive, directives
from nikola import utils
from nikola.plugin_categories import RestExtension
+# WARNING: the directive name is post-list
+# (with a DASH instead of an UNDERSCORE)
+
class Plugin(RestExtension):
name = "rest_post_list"
diff --git a/nikola/plugins/compile/rest/slides.py b/nikola/plugins/compile/rest/slides.py
index 41c3314..203ae51 100644
--- a/nikola/plugins/compile/rest/slides.py
+++ b/nikola/plugins/compile/rest/slides.py
@@ -1,6 +1,6 @@
# -*- coding: utf-8 -*-
-# Copyright © 2012-2013 Roberto Alsina and others.
+# Copyright © 2012-2014 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 6fb3e99..a26806c 100644
--- a/nikola/plugins/compile/rest/soundcloud.py
+++ b/nikola/plugins/compile/rest/soundcloud.py
@@ -15,12 +15,13 @@ class Plugin(RestExtension):
def set_site(self, site):
self.site = site
directives.register_directive('soundcloud', SoundCloud)
+ directives.register_directive('soundcloud_playlist', SoundCloudPlaylist)
return super(Plugin, self).set_site(site)
CODE = ("""<iframe width="{width}" height="{height}"
scrolling="no" frameborder="no"
-src="https://w.soundcloud.com/player/?url=http://api.soundcloud.com/tracks/"""
+src="https://w.soundcloud.com/player/?url=http://api.soundcloud.com/{preslug}/"""
"""{sid}">
</iframe>""")
@@ -40,6 +41,7 @@ class SoundCloud(Directive):
'width': directives.positive_int,
'height': directives.positive_int,
}
+ preslug = "tracks"
def run(self):
""" Required by the Directive interface. Create docutils nodes """
@@ -48,6 +50,7 @@ class SoundCloud(Directive):
'sid': self.arguments[0],
'width': 600,
'height': 160,
+ 'preslug': self.preslug,
}
options.update(self.options)
return [nodes.raw('', CODE.format(**options), format='html')]
@@ -58,3 +61,7 @@ class SoundCloud(Directive):
raise self.warning("This directive does not accept content. The "
"'key=value' format for options is deprecated, "
"use ':key: value' instead")
+
+
+class SoundCloudPlaylist(SoundCloud):
+ preslug = "playlists"
diff --git a/nikola/plugins/compile/rest/template.txt b/nikola/plugins/compile/rest/template.txt
new file mode 100644
index 0000000..2591bce
--- /dev/null
+++ b/nikola/plugins/compile/rest/template.txt
@@ -0,0 +1,8 @@
+%(head_prefix)s
+%(head)s
+%(stylesheet)s
+%(body_prefix)s
+%(body_pre_docinfo)s
+%(docinfo)s
+%(body)s
+%(body_suffix)s
diff --git a/nikola/plugins/compile/rest/vimeo.py b/nikola/plugins/compile/rest/vimeo.py
index 6d66648..82c4dc1 100644
--- a/nikola/plugins/compile/rest/vimeo.py
+++ b/nikola/plugins/compile/rest/vimeo.py
@@ -1,6 +1,6 @@
# -*- coding: utf-8 -*-
-# Copyright © 2012-2013 Roberto Alsina and others.
+# Copyright © 2012-2014 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/youtube.py b/nikola/plugins/compile/rest/youtube.py
index 3d4bdd3..19e12d1 100644
--- a/nikola/plugins/compile/rest/youtube.py
+++ b/nikola/plugins/compile/rest/youtube.py
@@ -1,6 +1,6 @@
# -*- coding: utf-8 -*-
-# Copyright © 2012-2013 Roberto Alsina and others.
+# Copyright © 2012-2014 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/textile.py b/nikola/plugins/compile/textile.py
index b402329..73f35c0 100644
--- a/nikola/plugins/compile/textile.py
+++ b/nikola/plugins/compile/textile.py
@@ -1,6 +1,6 @@
# -*- coding: utf-8 -*-
-# Copyright © 2012-2013 Roberto Alsina and others.
+# Copyright © 2012-2014 Roberto Alsina and others.
# Permission is hereby granted, free of charge, to any
# person obtaining a copy of this software and associated
@@ -38,11 +38,17 @@ except ImportError:
from nikola.plugin_categories import PageCompiler
from nikola.utils import makedirs, req_missing
+try:
+ from collections import OrderedDict
+except ImportError:
+ OrderedDict = None # NOQA
+
class CompileTextile(PageCompiler):
"""Compile textile into HTML."""
name = "textile"
+ demote_headers = True
def compile_html(self, source, dest, is_two_file=True):
if textile is None:
@@ -57,7 +63,10 @@ class CompileTextile(PageCompiler):
out_file.write(output)
def create_post(self, path, onefile=False, **kw):
- metadata = {}
+ if OrderedDict is not None:
+ metadata = OrderedDict()
+ else:
+ metadata = {}
metadata.update(self.default_metadata)
metadata.update(kw)
makedirs(os.path.dirname(path))
diff --git a/nikola/plugins/compile/txt2tags.py b/nikola/plugins/compile/txt2tags.py
index 2f62f04..8c9724e 100644
--- a/nikola/plugins/compile/txt2tags.py
+++ b/nikola/plugins/compile/txt2tags.py
@@ -1,6 +1,6 @@
# -*- coding: utf-8 -*-
-# Copyright © 2012-2013 Roberto Alsina and others.
+# Copyright © 2012-2014 Roberto Alsina and others.
# Permission is hereby granted, free of charge, to any
# person obtaining a copy of this software and associated
@@ -40,14 +40,20 @@ try:
except ImportError:
txt2tags = None # NOQA
+try:
+ from collections import OrderedDict
+except ImportError:
+ OrderedDict = None # NOQA
+
from nikola.plugin_categories import PageCompiler
from nikola.utils import makedirs, req_missing
-class CompileTextile(PageCompiler):
+class CompileTxt2tags(PageCompiler):
"""Compile txt2tags into HTML."""
name = "txt2tags"
+ demote_headers = True
def compile_html(self, source, dest, is_two_file=True):
if txt2tags is None:
@@ -57,7 +63,10 @@ class CompileTextile(PageCompiler):
txt2tags(cmd)
def create_post(self, path, onefile=False, **kw):
- metadata = {}
+ if OrderedDict is not None:
+ metadata = OrderedDict()
+ else:
+ metadata = {}
metadata.update(self.default_metadata)
metadata.update(kw)
makedirs(os.path.dirname(path))
diff --git a/nikola/plugins/compile/wiki.py b/nikola/plugins/compile/wiki.py
index b2c4afc..9a365fa 100644
--- a/nikola/plugins/compile/wiki.py
+++ b/nikola/plugins/compile/wiki.py
@@ -1,6 +1,6 @@
# -*- coding: utf-8 -*-
-# Copyright © 2012-2013 Roberto Alsina and others.
+# Copyright © 2012-2014 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,11 @@ except ImportError:
creole = None
from nikola.plugin_categories import PageCompiler
+try:
+ from collections import OrderedDict
+except ImportError:
+ OrderedDict = None # NOQA
+
from nikola.utils import makedirs, req_missing
@@ -44,6 +49,7 @@ class CompileWiki(PageCompiler):
"""Compile CreoleWiki into HTML."""
name = "wiki"
+ demote_headers = True
def compile_html(self, source, dest, is_two_file=True):
if creole is None:
@@ -57,7 +63,10 @@ class CompileWiki(PageCompiler):
out_file.write(output)
def create_post(self, path, onefile=False, **kw):
- metadata = {}
+ if OrderedDict is not None:
+ metadata = OrderedDict()
+ else:
+ metadata = {}
metadata.update(self.default_metadata)
metadata.update(kw)
makedirs(os.path.dirname(path))
diff --git a/nikola/plugins/loghandler/__init__.py b/nikola/plugins/loghandler/__init__.py
new file mode 100644
index 0000000..6ad8bac
--- /dev/null
+++ b/nikola/plugins/loghandler/__init__.py
@@ -0,0 +1,25 @@
+# -*- coding: utf-8 -*-
+
+# Copyright © 2012-2014 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 "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.
diff --git a/nikola/plugins/loghandler/smtp.py b/nikola/plugins/loghandler/smtp.py
index deb8f4e..2c9fd9c 100644
--- a/nikola/plugins/loghandler/smtp.py
+++ b/nikola/plugins/loghandler/smtp.py
@@ -1,6 +1,6 @@
# -*- coding: utf-8 -*-
-# Copyright © 2012-2013 Daniel Devine and others.
+# Copyright © 2012-2014 Daniel Devine 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/loghandler/stderr.py b/nikola/plugins/loghandler/stderr.py
index 71f1de5..75acffc 100644
--- a/nikola/plugins/loghandler/stderr.py
+++ b/nikola/plugins/loghandler/stderr.py
@@ -1,6 +1,6 @@
# -*- coding: utf-8 -*-
-# Copyright © 2012-2013 Daniel Devine and others.
+# Copyright © 2012-2014 Daniel Devine and others.
# Permission is hereby granted, free of charge, to any
# person obtaining a copy of this software and associated
@@ -29,6 +29,8 @@ from blinker import signal
import logbook
import os
+from nikola import DEBUG
+
class StderrHandler(SignalHandler):
"""Logs messages to stderr."""
@@ -39,7 +41,7 @@ class StderrHandler(SignalHandler):
conf = self.site.config.get('LOGGING_HANDLERS').get('stderr')
if conf or os.getenv('NIKOLA_DEBUG'):
self.site.loghandlers.append(logbook.StderrHandler(
- level='DEBUG' if os.getenv('NIKOLA_DEBUG') else conf.get('loglevel', 'WARNING').upper(),
+ level='DEBUG' if DEBUG else conf.get('loglevel', 'WARNING').upper(),
format_string=u'[{record.time:%Y-%m-%dT%H:%M:%SZ}] {record.level_name}: {record.channel}: {record.message}'
))
diff --git a/nikola/plugins/task/__init__.py b/nikola/plugins/task/__init__.py
index e69de29..6ad8bac 100644
--- a/nikola/plugins/task/__init__.py
+++ b/nikola/plugins/task/__init__.py
@@ -0,0 +1,25 @@
+# -*- coding: utf-8 -*-
+
+# Copyright © 2012-2014 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 "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.
diff --git a/nikola/plugins/task/archive.py b/nikola/plugins/task/archive.py
index 3afbea1..a65a63f 100644
--- a/nikola/plugins/task/archive.py
+++ b/nikola/plugins/task/archive.py
@@ -1,6 +1,6 @@
# -*- coding: utf-8 -*-
-# Copyright © 2012-2013 Roberto Alsina and others.
+# Copyright © 2012-2014 Roberto Alsina and others.
# Permission is hereby granted, free of charge, to any
# person obtaining a copy of this software and associated
@@ -92,7 +92,8 @@ class Archive(Task):
kw['filters'],
context,
)
- task_cfg = {1: task['uptodate'][0].config, 2: kw}
+ n = len(post_list) if 'posts' in context else len(months)
+ task_cfg = {1: task['uptodate'][0].config, 2: kw, 3: n}
task['uptodate'] = [config_changed(task_cfg)]
task['basename'] = self.name
yield task
@@ -123,7 +124,7 @@ class Archive(Task):
kw['filters'],
context,
)
- task_cfg = {1: task['uptodate'][0].config, 2: kw}
+ task_cfg = {1: task['uptodate'][0].config, 2: kw, 3: len(post_list)}
task['uptodate'] = [config_changed(task_cfg)]
task['basename'] = self.name
yield task
@@ -151,7 +152,7 @@ class Archive(Task):
kw['filters'],
context,
)
- task_cfg = {1: task['uptodate'][0].config, 2: kw}
+ task_cfg = {1: task['uptodate'][0].config, 2: kw, 3: len(years)}
task['uptodate'] = [config_changed(task_cfg)]
task['basename'] = self.name
yield task
diff --git a/nikola/plugins/task/build_less.py b/nikola/plugins/task/build_less.py
index 8889cbe..14a53f9 100644
--- a/nikola/plugins/task/build_less.py
+++ b/nikola/plugins/task/build_less.py
@@ -1,6 +1,6 @@
# -*- coding: utf-8 -*-
-# Copyright © 2012-2013 Roberto Alsina and others.
+# Copyright © 2012-2014 Roberto Alsina and others.
# Permission is hereby granted, free of charge, to any
# person obtaining a copy of this software and associated
@@ -29,6 +29,7 @@ from __future__ import unicode_literals
import codecs
import glob
import os
+import sys
import subprocess
from nikola.plugin_categories import Task
@@ -41,10 +42,10 @@ class BuildLess(Task):
name = "build_less"
sources_folder = "less"
sources_ext = ".less"
- compiler_name = "lessc"
def gen_tasks(self):
"""Generate CSS out of LESS sources."""
+ self.compiler_name = self.site.config['LESS_COMPILER']
kw = {
'cache_folder': self.site.config['CACHE_FOLDER'],
@@ -79,7 +80,13 @@ class BuildLess(Task):
def compile_target(target, dst):
utils.makedirs(dst_dir)
src = os.path.join(kw['cache_folder'], self.sources_folder, target)
- compiled = subprocess.check_output([self.compiler_name, src])
+ run_in_shell = sys.platform == 'win32'
+ try:
+ compiled = subprocess.check_output([self.compiler_name, src], shell=run_in_shell)
+ except OSError:
+ utils.req_missing([self.compiler_name],
+ 'build LESS files (and use this theme)',
+ False, False)
with open(dst, "wb+") as outf:
outf.write(compiled)
diff --git a/nikola/plugins/task/build_sass.py b/nikola/plugins/task/build_sass.py
index a5d22fb..7575505 100644
--- a/nikola/plugins/task/build_sass.py
+++ b/nikola/plugins/task/build_sass.py
@@ -1,6 +1,6 @@
# -*- coding: utf-8 -*-
-# Copyright © 2012-2013 Roberto Alsina and others.
+# Copyright © 2012-2014 Roberto Alsina and others.
# Permission is hereby granted, free of charge, to any
# person obtaining a copy of this software and associated
@@ -29,6 +29,7 @@ from __future__ import unicode_literals
import codecs
import glob
import os
+import sys
import subprocess
from nikola.plugin_categories import Task
@@ -41,11 +42,11 @@ class BuildSass(Task):
name = "build_sass"
sources_folder = "sass"
sources_ext = (".sass", ".scss")
- compiler_name = "sass"
def gen_tasks(self):
"""Generate CSS out of Sass sources."""
self.logger = utils.get_logger('build_sass', self.site.loghandlers)
+ self.compiler_name = self.site.config['SASS_COMPILER']
kw = {
'cache_folder': self.site.config['CACHE_FOLDER'],
@@ -79,8 +80,14 @@ class BuildSass(Task):
def compile_target(target, dst):
utils.makedirs(dst_dir)
+ run_in_shell = sys.platform == 'win32'
src = os.path.join(kw['cache_folder'], self.sources_folder, target)
- compiled = subprocess.check_output([self.compiler_name, src])
+ try:
+ compiled = subprocess.check_output([self.compiler_name, src], shell=run_in_shell)
+ except OSError:
+ utils.req_missing([self.compiler_name],
+ 'build Sass files (and use this theme)',
+ False, False)
with open(dst, "wb+") as outf:
outf.write(compiled)
@@ -99,7 +106,7 @@ class BuildSass(Task):
if base in seennames:
self.logger.error(
- 'Duplicate filenames for SASS compiled files: {0} and '
+ 'Duplicate filenames for Sass compiled files: {0} and '
'{1} (both compile to {2})'.format(
seennames[base], target, base + ".css"))
else:
diff --git a/nikola/plugins/task/bundles.py b/nikola/plugins/task/bundles.py
index 488f96f..b035b97 100644
--- a/nikola/plugins/task/bundles.py
+++ b/nikola/plugins/task/bundles.py
@@ -1,6 +1,6 @@
# -*- coding: utf-8 -*-
-# Copyright © 2012-2013 Roberto Alsina and others.
+# Copyright © 2012-2014 Roberto Alsina and others.
# Permission is hereby granted, free of charge, to any
# person obtaining a copy of this software and associated
@@ -44,7 +44,9 @@ class BuildBundles(LateTask):
def set_site(self, site):
super(BuildBundles, self).set_site(site)
- if webassets is None:
+ if webassets is None and self.site.config['USE_BUNDLES']:
+ utils.req_missing(['webassets'], 'USE_BUNDLES', optional=True)
+ utils.LOGGER.warn('Setting USE_BUNDLES to False.')
self.site.config['USE_BUNDLES'] = False
def gen_tasks(self):
@@ -111,6 +113,6 @@ def get_theme_bundles(themes):
for line in fd:
name, files = line.split('=')
files = [f.strip() for f in files.split(',')]
- bundles[name.strip()] = files
+ bundles[name.strip().replace('/', os.sep)] = files
break
return bundles
diff --git a/nikola/plugins/task/copy_assets.py b/nikola/plugins/task/copy_assets.py
index f3d85df..21f1f85 100644
--- a/nikola/plugins/task/copy_assets.py
+++ b/nikola/plugins/task/copy_assets.py
@@ -1,6 +1,6 @@
# -*- coding: utf-8 -*-
-# Copyright © 2012-2013 Roberto Alsina and others.
+# Copyright © 2012-2014 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/task/copy_files.py b/nikola/plugins/task/copy_files.py
index 88e89eb..9846ca0 100644
--- a/nikola/plugins/task/copy_files.py
+++ b/nikola/plugins/task/copy_files.py
@@ -1,6 +1,6 @@
# -*- coding: utf-8 -*-
-# Copyright © 2012-2013 Roberto Alsina and others.
+# Copyright © 2012-2014 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/task/galleries.py b/nikola/plugins/task/galleries.py
index cf670e0..6977eab 100644
--- a/nikola/plugins/task/galleries.py
+++ b/nikola/plugins/task/galleries.py
@@ -1,6 +1,6 @@
# -*- coding: utf-8 -*-
-# Copyright © 2012-2013 Roberto Alsina and others.
+# Copyright © 2012-2014 Roberto Alsina and others.
# Permission is hereby granted, free of charge, to any
# person obtaining a copy of this software and associated
@@ -51,6 +51,7 @@ import PyRSS2Gen as rss
from nikola.plugin_categories import Task
from nikola import utils
from nikola.post import Post
+from nikola.utils import req_missing
class Galleries(Task):
@@ -77,6 +78,9 @@ class Galleries(Task):
def gen_tasks(self):
"""Render image galleries."""
+ if Image is None:
+ req_missing(['pillow'], 'render galleries')
+
self.logger = utils.get_logger('render_galleries', self.site.loghandlers)
self.image_ext_list = ['.jpg', '.png', '.jpeg', '.gif', '.svg', '.bmp', '.tiff']
self.image_ext_list.extend(self.site.config.get('EXTRA_IMAGE_EXTENSIONS', []))
@@ -111,7 +115,7 @@ class Galleries(Task):
for gallery in self.gallery_list:
# Create subfolder list
- folder_list = [x.split(os.sep)[-2] for x in
+ folder_list = [(x, x.split(os.sep)[-2]) for x in
glob.glob(os.path.join(gallery, '*') + os.sep)]
# Parse index into a post (with translations)
@@ -137,7 +141,7 @@ class Galleries(Task):
for task in self.remove_excluded_image(image):
yield task
- crumbs = utils.get_crumbs(gallery)
+ crumbs = utils.get_crumbs(gallery, index_folder=self)
# Create index.html for each language
for lang in self.kw['translations']:
@@ -173,9 +177,20 @@ class Galleries(Task):
thumbs = ['.thumbnail'.join(os.path.splitext(p)) for p in image_list]
thumbs = [os.path.join(self.kw['output_folder'], t) for t in thumbs]
+ folders = []
+
+ # Generate friendly gallery names
+ for path, folder in folder_list:
+ fpost = self.parse_index(path)
+ if fpost:
+ ft = fpost.title(lang) or folder
+ else:
+ ft = folder
+ folders.append((folder, ft))
+
## TODO: in v7 remove images from context, use photo_array
context["images"] = list(zip(image_name_list, thumbs, img_titles))
- context["folders"] = folder_list
+ context["folders"] = folders
context["crumbs"] = crumbs
context["permalink"] = self.site.link(
"gallery", os.path.basename(gallery), lang)
@@ -288,8 +303,14 @@ class Galleries(Task):
False,
self.site.MESSAGES,
'story.tmpl',
- self.site.get_compiler(index_path).compile_html
+ self.site.get_compiler(index_path)
)
+ # If this did not exist, galleries without a title in the
+ # index.txt file would be errorneously named `index`
+ # (warning: galleries titled index and filenamed differently
+ # may break)
+ if post.title == 'index':
+ post.title = os.path.split(gallery)[1]
else:
post = None
return post
@@ -460,7 +481,7 @@ class Galleries(Task):
os.path.join(
self.site.config['OUTPUT_FOLDER'], img)).st_size
args = {
- 'title': full_title.split('"')[-2],
+ 'title': full_title.split('"')[-2] if full_title else '',
'link': make_url(img),
'guid': rss.Guid(img, False),
'pubDate': self.image_date(img),
@@ -477,7 +498,7 @@ class Galleries(Task):
description='',
lastBuildDate=datetime.datetime.now(),
items=items,
- generator='nikola',
+ generator='Nikola <http://getnikola.com/>',
language=lang
)
rss_obj.self_url = make_url(permalink)
@@ -523,8 +544,9 @@ class Galleries(Task):
try:
im.thumbnail(size, Image.ANTIALIAS)
im.save(dst)
- except Exception:
- self.logger.warn("Can't thumbnail {0}, using original image as thumbnail".format(src))
+ except Exception as e:
+ self.logger.warn("Can't thumbnail {0}, using original "
+ "image as thumbnail ({1})".format(src, e))
utils.copy_file(src, dst)
else: # Image is small
utils.copy_file(src, dst)
diff --git a/nikola/plugins/task/gzip.py b/nikola/plugins/task/gzip.py
index 738d52c..bcc9637 100644
--- a/nikola/plugins/task/gzip.py
+++ b/nikola/plugins/task/gzip.py
@@ -1,6 +1,6 @@
# -*- coding: utf-8 -*-
-# Copyright © 2012-2013 Roberto Alsina and others.
+# Copyright © 2012-2014 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/task/indexes.py b/nikola/plugins/task/indexes.py
index 0d20422..3f45161 100644
--- a/nikola/plugins/task/indexes.py
+++ b/nikola/plugins/task/indexes.py
@@ -1,6 +1,6 @@
# -*- coding: utf-8 -*-
-# Copyright © 2012-2013 Roberto Alsina and others.
+# Copyright © 2012-2014 Roberto Alsina and others.
# Permission is hereby granted, free of charge, to any
# person obtaining a copy of this software and associated
@@ -57,6 +57,7 @@ class Indexes(Task):
"hide_untranslated_posts": self.site.config['HIDE_UNTRANSLATED_POSTS'],
"indexes_title": self.site.config['INDEXES_TITLE'],
"indexes_pages": self.site.config['INDEXES_PAGES'],
+ "indexes_pages_main": self.site.config['INDEXES_PAGES_MAIN'],
"blog_title": self.site.config["BLOG_TITLE"],
}
@@ -78,12 +79,18 @@ class Indexes(Task):
for i, post_list in enumerate(lists):
context = {}
indexes_title = kw['indexes_title'] or kw['blog_title']
+ if kw["indexes_pages_main"]:
+ ipages_i = i + 1
+ ipages_msg = "page %d"
+ else:
+ ipages_i = i
+ ipages_msg = "old posts, page %d"
if kw["indexes_pages"]:
- indexes_pages = kw["indexes_pages"] % i
+ indexes_pages = kw["indexes_pages"] % ipages_i
else:
indexes_pages = " (" + \
- kw["messages"][lang]["old posts page %d"] % i + ")"
- if i > 0:
+ kw["messages"][lang][ipages_msg] % ipages_i + ")"
+ if i > 0 or kw["indexes_pages_main"]:
context["title"] = indexes_title + indexes_pages
else:
context["title"] = indexes_title
diff --git a/nikola/plugins/task/listings.py b/nikola/plugins/task/listings.py
index ab62e74..d8ed43b 100644
--- a/nikola/plugins/task/listings.py
+++ b/nikola/plugins/task/listings.py
@@ -1,6 +1,6 @@
# -*- coding: utf-8 -*-
-# Copyright © 2012-2013 Roberto Alsina and others.
+# Copyright © 2012-2014 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/task/localsearch/__init__.py b/nikola/plugins/task/localsearch/__init__.py
index 9162604..c501d80 100644
--- a/nikola/plugins/task/localsearch/__init__.py
+++ b/nikola/plugins/task/localsearch/__init__.py
@@ -1,6 +1,6 @@
# -*- coding: utf-8 -*-
-# Copyright © 2012-2013 Roberto Alsina and others.
+# Copyright © 2012-2014 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/task/mustache/__init__.py b/nikola/plugins/task/mustache/__init__.py
index c392e3b..5be98f0 100644
--- a/nikola/plugins/task/mustache/__init__.py
+++ b/nikola/plugins/task/mustache/__init__.py
@@ -1,6 +1,6 @@
# -*- coding: utf-8 -*-
-# Copyright © 2012-2013 Roberto Alsina and others.
+# Copyright © 2012-2014 Roberto Alsina and others.
# Permission is hereby granted, free of charge, to any
# person obtaining a copy of this software and associated
@@ -31,7 +31,9 @@ import json
import os
from nikola.plugin_categories import Task
-from nikola.utils import config_changed, copy_file, unicode_str, makedirs
+from nikola.utils import (
+ config_changed, copy_file, LocaleBorg, makedirs, unicode_str,
+)
class Mustache(Task):
@@ -106,7 +108,7 @@ class Mustache(Task):
})
# Comments
- context = dict(post=post, lang=self.site.current_lang())
+ context = dict(post=post, lang=LocaleBorg().current_lang)
context.update(self.site.GLOBAL_CONTEXT)
data["comment_html"] = self.site.template_system.render_template(
'mustache-comment-form.tmpl', None, context).strip()
diff --git a/nikola/plugins/task/pages.py b/nikola/plugins/task/pages.py
index eb5b49e..f4c0469 100644
--- a/nikola/plugins/task/pages.py
+++ b/nikola/plugins/task/pages.py
@@ -1,6 +1,6 @@
# -*- coding: utf-8 -*-
-# Copyright © 2012-2013 Roberto Alsina and others.
+# Copyright © 2012-2014 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/task/posts.py b/nikola/plugins/task/posts.py
index 18d61b8..a502b81 100644
--- a/nikola/plugins/task/posts.py
+++ b/nikola/plugins/task/posts.py
@@ -1,6 +1,6 @@
# -*- coding: utf-8 -*-
-# Copyright © 2012-2013 Roberto Alsina and others.
+# Copyright © 2012-2014 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/task/redirect.py b/nikola/plugins/task/redirect.py
index ade878a..6fafd13 100644
--- a/nikola/plugins/task/redirect.py
+++ b/nikola/plugins/task/redirect.py
@@ -1,6 +1,6 @@
# -*- coding: utf-8 -*-
-# Copyright © 2012-2013 Roberto Alsina and others.
+# Copyright © 2012-2014 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/task/rss.py b/nikola/plugins/task/rss.py
index bcca4da..e5f7548 100644
--- a/nikola/plugins/task/rss.py
+++ b/nikola/plugins/task/rss.py
@@ -1,6 +1,6 @@
# -*- coding: utf-8 -*-
-# Copyright © 2012-2013 Roberto Alsina and others.
+# Copyright © 2012-2014 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/task/sitemap/__init__.py b/nikola/plugins/task/sitemap/__init__.py
index f34bc0a..0164000 100644
--- a/nikola/plugins/task/sitemap/__init__.py
+++ b/nikola/plugins/task/sitemap/__init__.py
@@ -1,6 +1,6 @@
# -*- coding: utf-8 -*-
-# Copyright © 2012-2013 Roberto Alsina and others.
+# Copyright © 2012-2014 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/task/sources.py b/nikola/plugins/task/sources.py
index 672f354..2324af2 100644
--- a/nikola/plugins/task/sources.py
+++ b/nikola/plugins/task/sources.py
@@ -1,6 +1,6 @@
# -*- coding: utf-8 -*-
-# Copyright © 2012-2013 Roberto Alsina and others.
+# Copyright © 2012-2014 Roberto Alsina and others.
# Permission is hereby granted, free of charge, to any
# person obtaining a copy of this software and associated
@@ -66,7 +66,7 @@ class Sources(Task):
if dest_ext == post.source_ext():
continue
if lang != kw["default_lang"]:
- source_lang = source + '.' + lang
+ source_lang = utils.get_translation_candidate(self.site.config, source, lang)
if os.path.exists(source_lang):
source = source_lang
if os.path.isfile(source):
diff --git a/nikola/plugins/task/tags.py b/nikola/plugins/task/tags.py
index 299dca4..a2444ec 100644
--- a/nikola/plugins/task/tags.py
+++ b/nikola/plugins/task/tags.py
@@ -1,6 +1,6 @@
# -*- coding: utf-8 -*-
-# Copyright © 2012-2013 Roberto Alsina and others.
+# Copyright © 2012-2014 Roberto Alsina and others.
# Permission is hereby granted, free of charge, to any
# person obtaining a copy of this software and associated
@@ -110,8 +110,14 @@ class RenderTags(Task):
# Tag cloud json file
tag_cloud_data = {}
for tag, posts in self.site.posts_per_tag.items():
+ tag_posts = dict(posts=[{'title': post.meta[post.default_lang]['title'],
+ 'date': post.date.strftime('%m/%d/%Y'),
+ 'isodate': post.date.isoformat(),
+ 'url': post.base_path.replace('cache', '')}
+ for post in reversed(sorted(self.site.timeline, key=lambda post: post.date))
+ if tag in post.alltags])
tag_cloud_data[tag] = [len(posts), self.site.link(
- 'tag', tag, self.site.config['DEFAULT_LANG'])]
+ 'tag', tag, self.site.config['DEFAULT_LANG']), tag_posts]
output_name = os.path.join(kw['output_folder'],
'assets', 'js', 'tag_cloud_data.json')
@@ -124,6 +130,7 @@ class RenderTags(Task):
'basename': str(self.name),
'name': str(output_name)
}
+
task['uptodate'] = [utils.config_changed(tag_cloud_data)]
task['targets'] = [output_name]
task['actions'] = [(write_tag_data, [tag_cloud_data])]
@@ -189,7 +196,7 @@ class RenderTags(Task):
return name
# FIXME: deduplicate this with render_indexes
- template_name = "index.tmpl"
+ template_name = "tagindex.tmpl"
# Split in smaller lists
lists = []
while post_list:
diff --git a/nikola/plugins/template/__init__.py b/nikola/plugins/template/__init__.py
index e69de29..6ad8bac 100644
--- a/nikola/plugins/template/__init__.py
+++ b/nikola/plugins/template/__init__.py
@@ -0,0 +1,25 @@
+# -*- coding: utf-8 -*-
+
+# Copyright © 2012-2014 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 "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.
diff --git a/nikola/plugins/template/jinja.py b/nikola/plugins/template/jinja.py
index a40a476..17c33d4 100644
--- a/nikola/plugins/template/jinja.py
+++ b/nikola/plugins/template/jinja.py
@@ -1,6 +1,6 @@
# -*- coding: utf-8 -*-
-# Copyright © 2012-2013 Roberto Alsina and others.
+# Copyright © 2012-2014 Roberto Alsina and others.
# Permission is hereby granted, free of charge, to any
# person obtaining a copy of this software and associated
@@ -55,7 +55,7 @@ class JinjaTemplates(TemplateSystem):
self.lookup.globals['enumerate'] = enumerate
def set_directories(self, directories, cache_folder):
- """Createa template lookup."""
+ """Create a template lookup."""
if jinja2 is None:
req_missing(['jinja2'], 'use this theme')
self.lookup.loader = jinja2.FileSystemLoader(directories,
@@ -74,9 +74,8 @@ class JinjaTemplates(TemplateSystem):
return output
def render_template_to_string(self, template, context):
- """ Render template to a string using context. """
-
- return jinja2.Template(template).render(**context)
+ """Render template to a string using context."""
+ return self.lookup.from_string(template).render(**context)
def template_deps(self, template_name):
# Cache the lists of dependencies for each template name.
diff --git a/nikola/plugins/template/mako.py b/nikola/plugins/template/mako.py
index ae51cac..45f4335 100644
--- a/nikola/plugins/template/mako.py
+++ b/nikola/plugins/template/mako.py
@@ -1,6 +1,6 @@
# -*- coding: utf-8 -*-
-# Copyright © 2012-2013 Roberto Alsina and others.
+# Copyright © 2012-2014 Roberto Alsina and others.
# Permission is hereby granted, free of charge, to any
# person obtaining a copy of this software and associated