aboutsummaryrefslogtreecommitdiffstats
path: root/nikola
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
parentca94afc07df55cb7fc6fe3b4f3011877b7881195 (diff)
Imported Upstream version 6.3.0upstream/6.3.0
Diffstat (limited to 'nikola')
-rw-r--r--nikola/__init__.py30
-rw-r--r--nikola/__main__.py (renamed from nikola/main.py)25
-rw-r--r--nikola/conf.py.in78
-rw-r--r--nikola/data/samplesite/files/assets/css/custom.css0
-rw-r--r--nikola/data/samplesite/galleries/demo/index.txt4
-rw-r--r--nikola/data/themes/base/assets/css/theme.css1
-rw-r--r--nikola/data/themes/base/assets/js/mathjax.js9
-rw-r--r--nikola/data/themes/base/messages/messages_bg.py8
-rw-r--r--nikola/data/themes/base/messages/messages_ca.py6
-rw-r--r--nikola/data/themes/base/messages/messages_cs.py29
l---------nikola/data/themes/base/messages/messages_cz.py1
-rw-r--r--nikola/data/themes/base/messages/messages_de.py6
-rw-r--r--nikola/data/themes/base/messages/messages_el.py8
-rw-r--r--nikola/data/themes/base/messages/messages_en.py8
-rw-r--r--nikola/data/themes/base/messages/messages_eo.py8
-rw-r--r--nikola/data/themes/base/messages/messages_es.py6
-rw-r--r--nikola/data/themes/base/messages/messages_et.py29
-rw-r--r--nikola/data/themes/base/messages/messages_eu.py29
-rw-r--r--nikola/data/themes/base/messages/messages_fa.py6
-rw-r--r--nikola/data/themes/base/messages/messages_fi.py6
-rw-r--r--nikola/data/themes/base/messages/messages_fr.py22
-rw-r--r--nikola/data/themes/base/messages/messages_hr.py10
-rw-r--r--nikola/data/themes/base/messages/messages_it.py6
-rw-r--r--nikola/data/themes/base/messages/messages_ja.py12
-rw-r--r--nikola/data/themes/base/messages/messages_nb.py29
-rw-r--r--nikola/data/themes/base/messages/messages_nl.py6
-rw-r--r--nikola/data/themes/base/messages/messages_pl.py10
-rw-r--r--nikola/data/themes/base/messages/messages_pt_br.py6
-rw-r--r--nikola/data/themes/base/messages/messages_ru.py6
-rw-r--r--nikola/data/themes/base/messages/messages_sl.py6
l---------nikola/data/themes/base/messages/messages_tr.py1
-rw-r--r--nikola/data/themes/base/messages/messages_tr_tr.py10
-rw-r--r--nikola/data/themes/base/messages/messages_ur.py29
-rw-r--r--nikola/data/themes/base/messages/messages_zh_cn.py10
-rw-r--r--nikola/data/themes/base/templates/base.tmpl2
-rw-r--r--nikola/data/themes/base/templates/base_helper.tmpl9
-rw-r--r--nikola/data/themes/base/templates/comments_helper.tmpl14
-rw-r--r--nikola/data/themes/base/templates/disqus_helper.tmpl22
-rw-r--r--nikola/data/themes/base/templates/gallery.tmpl8
-rw-r--r--nikola/data/themes/base/templates/index.tmpl6
-rwxr-xr-x[-rw-r--r--]nikola/data/themes/base/templates/index_helper.tmpl32
-rw-r--r--nikola/data/themes/base/templates/isso_helper.tmpl20
-rw-r--r--nikola/data/themes/base/templates/post.tmpl7
-rwxr-xr-x[-rw-r--r--]nikola/data/themes/base/templates/post_helper.tmpl51
-rw-r--r--nikola/data/themes/base/templates/tagindex.tmpl2
-rw-r--r--nikola/data/themes/bootstrap/assets/css/theme.css18
-rw-r--r--nikola/data/themes/bootstrap/templates/bootstrap_helper.tmpl5
-rw-r--r--nikola/data/themes/bootstrap/templates/gallery.tmpl8
-rw-r--r--nikola/filters.py26
-rw-r--r--nikola/nikola.py68
-rw-r--r--nikola/plugin_categories.py32
-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
-rw-r--r--nikola/post.py99
-rw-r--r--nikola/rc4.py2
-rw-r--r--nikola/utils.py77
-rw-r--r--nikola/winutils.py2
128 files changed, 1340 insertions, 431 deletions
diff --git a/nikola/__init__.py b/nikola/__init__.py
index a04e3b9..0a82198 100644
--- a/nikola/__init__.py
+++ b/nikola/__init__.py
@@ -1,8 +1,34 @@
# -*- 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.
+
from __future__ import absolute_import
+import os
+
+__version__ = "6.3.0"
+DEBUG = bool(os.getenv('NIKOLA_DEBUG'))
from .nikola import Nikola # NOQA
from . import plugins # NOQA
-
-__version__ = "6.2.1"
diff --git a/nikola/main.py b/nikola/__main__.py
index f00a4d2..6b549b4 100644
--- a/nikola/main.py
+++ b/nikola/__main__.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,12 @@ from doit.doit_cmd import DoitMain
from doit.cmd_help import Help as DoitHelp
from doit.cmd_run import Run as DoitRun
from doit.cmd_clean import Clean as DoitClean
+from doit.cmd_auto import Auto as DoitAuto
from logbook import NullHandler
from . import __version__
from .nikola import Nikola
-from .utils import _reload, sys_decode, LOGGER, STRICT_HANDLER
+from .utils import _reload, sys_decode, get_root_dir, LOGGER, STRICT_HANDLER
config = {}
@@ -58,6 +59,11 @@ def main(args):
nullhandler.push_application()
quiet = True
global config
+
+ root = get_root_dir()
+ if root:
+ os.chdir(root)
+
sys.path.append('')
try:
import conf
@@ -127,6 +133,10 @@ class Clean(DoitClean):
shutil.rmtree(cache_folder)
return super(Clean, self).clean_tasks(tasks, dryrun)
+# Nikola has its own "auto" commands that uses livereload.
+# Expose original doit "auto" command as "doit_auto".
+DoitAuto.name = 'doit_auto'
+
class NikolaTaskLoader(TaskLoader):
"""custom task loader to get tasks from Nikola instead of dodo.py file"""
@@ -156,7 +166,7 @@ class NikolaTaskLoader(TaskLoader):
class DoitNikola(DoitMain):
# overwite help command
- DOIT_CMDS = list(DoitMain.DOIT_CMDS) + [Help, Build, Clean]
+ DOIT_CMDS = list(DoitMain.DOIT_CMDS) + [Help, Build, Clean, DoitAuto]
TASK_LOADER = NikolaTaskLoader
def __init__(self, nikola, quiet=False):
@@ -181,7 +191,9 @@ class DoitNikola(DoitMain):
args = ['help']
# Hide run because Nikola uses build
sub_cmds.pop('run')
-
+ if len(args) == 0 or any(arg in ["--version", '-V'] for arg in args):
+ cmd_args = ['version']
+ args = ['version']
if len(args) == 0 or args[0] not in sub_cmds.keys() or \
args[0] == 'build':
# Check for conf.py before launching run
@@ -193,4 +205,7 @@ class DoitNikola(DoitMain):
@staticmethod
def print_version():
- print("Nikola version " + __version__)
+ print("Nikola v" + __version__)
+
+if __name__ == "__main__":
+ sys.exit(main(sys.argv[1:]))
diff --git a/nikola/conf.py.in b/nikola/conf.py.in
index 20605d8..6ae0e1d 100644
--- a/nikola/conf.py.in
+++ b/nikola/conf.py.in
@@ -25,28 +25,33 @@ BLOG_DESCRIPTION = "${BLOG_DESCRIPTION}"
# Currently supported languages are:
# bg Bulgarian
# ca Catalan
+# cs Czech [ALTERNATIVELY cz]
# de German
# el Greek [NOT gr!]
# en English
# eo Esperanto
# es Spanish
+# et Estonian
+# eu Basque
# fa Persian
# fi Finnish
# fr French
# hr Croatian
# it Italian
-# jp Japanese
+# ja Japanese [NOT jp!]
+# nb Norwegian Bokmål
# nl Dutch
# pt_br Portuguese (Brasil)
# pl Polish
# ru Russian
# sl Slovenian [NOT sl_si!]
-# tr_tr Turkish (Turkey)
+# tr Turkish (Turkey) [NOT tr_tr!]
+# ur Urdu
# zh_cn Chinese (Simplified)
#
# If you want to use Nikola with a non-supported language you have to provide
# a module containing the necessary translations
-# (p.e. look at the modules at: ./nikola/data/themes/default/messages/fr.py).
+# (cf. the modules at nikola/data/themes/base/messages/fr.py).
# If a specific post is not translated to a language, then the version
# in the default language will be shown instead.
@@ -62,6 +67,20 @@ TRANSLATIONS = {
# "es": "./es",
}
+# What will translated input files be named like?
+
+# If you have a page something.rst, then something.rst.pl will be considered
+# its Polish translation.
+# (in the above example: path == "something", lang == "pl", ext == "rst")
+# this pattern is also used for metadata:
+# something.meta -> something.meta.pl
+
+TRANSLATIONS_PATTERN = "{path}.{ext}.{lang}"
+
+# If you don't want your Polish files to be considered Perl code, use this:
+# TRANSLATIONS_PATTERN = "{path}.{lang}.{ext}"
+# Note that this pattern will become the default in v7.0.0.
+
# Links for the sidebar / navigation bar.
# You should provide a key-value pair for each used language.
NAVIGATION_LINKS = {
@@ -96,6 +115,8 @@ NAVIGATION_LINKS = {
# and optionally translated files (example for spanish, with code "es"):
# whatever/thing.txt.es and whatever/thing.meta.es
#
+# This assumes you use the default TRANSLATIONS_PATTERN.
+#
# From those files, a set of HTML fragment files will be generated:
# cache/whatever/thing.html (and maybe cache/whatever/thing.html.es)
#
@@ -165,6 +186,12 @@ COMPILERS = ${COMPILERS}
# ARCHIVE_PATH = ""
# ARCHIVE_FILENAME = "archive.html"
+# URLs to other posts/pages can take 3 forms:
+# rel_path: a relative URL to the current page/post (default)
+# full_path: a URL with the full path from the root
+# absolute: a complete URL (that includes the SITE_URL)
+# URL_TYPE = 'rel_path'
+
# Final locations are:
# output / TRANSLATION[lang] / RSS_PATH / rss.xml
# RSS_PATH = ""
@@ -187,7 +214,7 @@ COMPILERS = ${COMPILERS}
# Commands to execute to deploy. Can be anything, for example,
# you may use rsync:
-# "rsync -rav output/* joe@my.site:/srv/www/site"
+# "rsync -rav --delete output/ joe@my.site:/srv/www/site"
# And then do a backup, or run `nikola ping` from the `ping`
# plugin (`nikola install_plugin ping`).
# To do manual deployment, set it to []
@@ -235,11 +262,17 @@ COMPILERS = ${COMPILERS}
# Use an external gzip command? None means no.
# Example: GZIP_COMMAND = "pigz -k {filename}"
# GZIP_COMMAND = None
-# Make sure the server does not return a "Accept-Ranges: bytes" header for
+# Make sure the server does not return a "Accept-Ranges: bytes" header for
# files compressed by this option! OR make sure that a ranged request does not
# return partial content of another representation for these resources. Do not
# use this feature if you do not understand what this means.
+# Compiler to process LESS files.
+# LESS_COMPILER = 'lessc'
+
+# Compiler to process Sass files.
+# SASS_COMPILER = 'sass'
+
# #############################################################################
# Image Gallery Options
# #############################################################################
@@ -259,10 +292,13 @@ COMPILERS = ${COMPILERS}
# HTML fragments and diverse things that are used by the templates
# #############################################################################
-# Data about post-per-page indexes
-# INDEXES_TITLE = "" # If this is empty, the default is BLOG_TITLE
-# INDEXES_PAGES = "" # If this is empty, the default is 'old posts page %d'
-# translated
+# Data about post-per-page indexes.
+# INDEXES_PAGES defaults to 'old posts, page %d' or 'page %d' (translated),
+# depending on the value of INDEXES_PAGES_MAIN.
+# INDEXES_TITLE = "" # If this is empty, defaults to BLOG_TITLE
+# INDEXES_PAGES = "" # If this is empty, defaults to '[old posts,] page %d' (see above)
+# INDEXES_PAGES_MAIN = False # If True, INDEXES_PAGES is also displayed on
+ # the main (the newest) index page (index.html)
# Name of the theme to use.
THEME = "${THEME}"
@@ -330,7 +366,7 @@ CONTENT_FOOTER = CONTENT_FOOTER.format(email=BLOG_EMAIL,
# To use comments, you can choose between different third party comment
# systems, one of "disqus", "livefyre", "intensedebate", "moot",
-# "googleplus" or "facebook"
+# "googleplus", "facebook" or "isso"
# COMMENT_SYSTEM = "disqus"
# And you also need to add your COMMENT_SYSTEM_ID which
# depends on what comment system you use. The default is
@@ -583,14 +619,15 @@ CONTENT_FOOTER = CONTENT_FOOTER.format(email=BLOG_EMAIL,
# }
-# Post's dates are considered in GMT by default, if you want to use
-# another timezone, please set TIMEZONE to match. Check the available
+# Post's dates are considered in UTC by default, if you want to use
+# another time zone, please set TIMEZONE to match. Check the available
# list from Wikipedia:
# http://en.wikipedia.org/wiki/List_of_tz_database_time_zones
-# Also, if you want to use a different timezone in some of your posts,
+# (eg. 'Europe/Zurich')
+# Also, if you want to use a different time zone in some of your posts,
# you can use W3C-DTF Format (ex. 2012-03-30T23:00:00+02:00)
#
-# TIMEZONE = 'Europe/Zurich'
+# TIMEZONE = 'UTC'
# If webassets is installed, bundle JS and CSS to make site loading faster
# USE_BUNDLES = True
@@ -598,6 +635,11 @@ CONTENT_FOOTER = CONTENT_FOOTER.format(email=BLOG_EMAIL,
# Plugins you don't want to use. Be careful :-)
# DISABLED_PLUGINS = ["render_galleries"]
+# Add the absolute paths to directories containing plugins to use them.
+# For example, the `plugins` directory of your clone of the Nikola plugins
+# repository.
+# EXTRA_PLUGINS_DIRS = []
+
# Experimental plugins - use at your own risk.
# They probably need some manual adjustments - please see their respective
# readme.
@@ -615,6 +657,14 @@ CONTENT_FOOTER = CONTENT_FOOTER.format(email=BLOG_EMAIL,
# If set to True, enable optional hyphenation in your posts (requires pyphen)
# HYPHENATE = False
+# The <hN> tags in HTML generated by certain compilers (reST/Markdown)
+# will be demoted by that much (1 → h1 will become h2 and so on)
+# This was a hidden feature of the Markdown and reST compilers in the
+# past. Useful especially if your post titles are in <h1> tags too, for
+# example.
+# (defaults to 1.)
+# DEMOTE_HEADERS = 1
+
# You can configure the logging handlers installed as plugins or change the
# log level of the default stdout handler.
LOGGING_HANDLERS = {
diff --git a/nikola/data/samplesite/files/assets/css/custom.css b/nikola/data/samplesite/files/assets/css/custom.css
deleted file mode 100644
index e69de29..0000000
--- a/nikola/data/samplesite/files/assets/css/custom.css
+++ /dev/null
diff --git a/nikola/data/samplesite/galleries/demo/index.txt b/nikola/data/samplesite/galleries/demo/index.txt
index d3d5a44..e29f66e 100644
--- a/nikola/data/samplesite/galleries/demo/index.txt
+++ b/nikola/data/samplesite/galleries/demo/index.txt
@@ -1,2 +1,4 @@
+.. title: Nikola Tesla
+
Some public domain pictures of Nikola Tesla
-(copied from `here <http://kerryr.net/pioneers/gallery/tesla.htm>`_) \ No newline at end of file
+(copied from `here <http://kerryr.net/pioneers/gallery/tesla.htm>`_)
diff --git a/nikola/data/themes/base/assets/css/theme.css b/nikola/data/themes/base/assets/css/theme.css
index e69de29..2a924f1 100644
--- a/nikola/data/themes/base/assets/css/theme.css
+++ b/nikola/data/themes/base/assets/css/theme.css
@@ -0,0 +1 @@
+/* This file intentionally left blank. */
diff --git a/nikola/data/themes/base/assets/js/mathjax.js b/nikola/data/themes/base/assets/js/mathjax.js
index 2f4e773..82c1f6c 100644
--- a/nikola/data/themes/base/assets/js/mathjax.js
+++ b/nikola/data/themes/base/assets/js/mathjax.js
@@ -6,7 +6,12 @@ window.onload = function () {
setTimeout(function () {
var script = document.createElement("script");
script.type = "text/javascript";
- script.src = "https://c328740.ssl.cf1.rackcdn.com/mathjax/latest/MathJax.js?config=TeX-AMS_HTML";
+ if (location.protocol == 'https:') {
+ scriptbase = "https://c328740.ssl.cf1.rackcdn.com/";
+ } else {
+ scriptbase = "http://cdn.mathjax.org/";
+ }
+ script.src = scriptbase + "mathjax/latest/MathJax.js?config=TeX-AMS-MML_HTMLorMML";
document.getElementsByTagName("body")[0].appendChild(script);
},1)
-} \ No newline at end of file
+}
diff --git a/nikola/data/themes/base/messages/messages_bg.py b/nikola/data/themes/base/messages/messages_bg.py
index 2d36959..d4881b5 100644
--- a/nikola/data/themes/base/messages/messages_bg.py
+++ b/nikola/data/themes/base/messages/messages_bg.py
@@ -3,15 +3,18 @@ from __future__ import unicode_literals
MESSAGES = {
"Also available in": "Също достъпно в",
+ "Also available in:": "Също достъпно в:",
"Archive": "Архив",
"Categories": "Категории",
"LANGUAGE": "Български",
- "More posts about": "Още публикации относно ",
+ "More posts about %s": "Още публикации относно %s",
+ "More posts about": "Още публикации относно",
"Newer posts": "Нови публикации",
"Next post": "Следваща публикация",
"Older posts": "Стари публикации",
"Original site": "Оригиналния сайт",
"Posted": "Публиковано",
+ "Posted:": "Публиковано:",
"Posts about %s": "Публикации относно %s",
"Posts for year %s": "Публикации за %s година",
"Posts for {month} {year}": "Публикации за {month} {year}",
@@ -21,5 +24,6 @@ MESSAGES = {
"Source": "Source",
"Tags and Categories": "Тагове и Категории",
"Tags": "Тагове",
- "old posts page %d": "стари публикации страница %d",
+ "old posts, page %d": "стари публикации, страница %d",
+ "page %d": "страница %d",
}
diff --git a/nikola/data/themes/base/messages/messages_ca.py b/nikola/data/themes/base/messages/messages_ca.py
index 80c4ee4..d3a97b5 100644
--- a/nikola/data/themes/base/messages/messages_ca.py
+++ b/nikola/data/themes/base/messages/messages_ca.py
@@ -3,15 +3,18 @@ from __future__ import unicode_literals
MESSAGES = {
"Also available in": "També disponibles en",
+ "Also available in:": "També disponibles en:",
"Archive": "Arxiu",
"Categories": "",
"LANGUAGE": "Català",
+ "More posts about %s": "Més entrades sobre %s",
"More posts about": "Més entrades sobre",
"Newer posts": "Entrades posteriors",
"Next post": "Entrada següent",
"Older posts": "Entrades anteriors",
"Original site": "Lloc original",
"Posted": "Publicat",
+ "Posted:": "Publicat:",
"Posts about %s": "Entrades sobre %s",
"Posts for year %s": "Entrades de l'any %s",
"Posts for {month} {year}": "",
@@ -21,5 +24,6 @@ MESSAGES = {
"Source": "Codi",
"Tags and Categories": "",
"Tags": "Etiquetes",
- "old posts page %d": "entrades antigues pàgina %d",
+ "old posts, page %d": "entrades antigues, pàgina %d",
+ "page %d": "pàgina %d",
}
diff --git a/nikola/data/themes/base/messages/messages_cs.py b/nikola/data/themes/base/messages/messages_cs.py
new file mode 100644
index 0000000..33482b5
--- /dev/null
+++ b/nikola/data/themes/base/messages/messages_cs.py
@@ -0,0 +1,29 @@
+# -*- encoding:utf-8 -*-
+from __future__ import unicode_literals
+
+MESSAGES = {
+ "Also available in": "Dostupné také v",
+ "Also available in:": "Dostupné také v",
+ "Archive": "Archiv",
+ "Categories": "Kategorie",
+ "LANGUAGE": "Čeština",
+ "More posts about %s": "Další příspěvky o %s",
+ "More posts about": "Další příspěvky o",
+ "Newer posts": "Novější příspěvky",
+ "Next post": "Další příspěvek",
+ "Older posts": "Starší příspěvky",
+ "Original site": "Původní stránka",
+ "Posted": "Zveřejněno",
+ "Posted:": "Zveřejněno:",
+ "Posts about %s": "Příspěvky o %s",
+ "Posts for year %s": "Příspěvky v roce %s",
+ "Posts for {month} {year}": "Příspěvky v {month} {year}",
+ "Previous post": "Předchozí příspěvek",
+ "Read in English": "Číst v češtině",
+ "Read more": "Číst dál",
+ "Source": "Zdroj",
+ "Tags and Categories": "Štítky a kategorie",
+ "Tags": "Štítky",
+ "old posts, page %d": "staré příspěvky, strana %d",
+ "page %d": "strana %d",
+}
diff --git a/nikola/data/themes/base/messages/messages_cz.py b/nikola/data/themes/base/messages/messages_cz.py
new file mode 120000
index 0000000..d784fd5
--- /dev/null
+++ b/nikola/data/themes/base/messages/messages_cz.py
@@ -0,0 +1 @@
+messages_cs.py \ No newline at end of file
diff --git a/nikola/data/themes/base/messages/messages_de.py b/nikola/data/themes/base/messages/messages_de.py
index c885304..6795031 100644
--- a/nikola/data/themes/base/messages/messages_de.py
+++ b/nikola/data/themes/base/messages/messages_de.py
@@ -3,15 +3,18 @@ from __future__ import unicode_literals
MESSAGES = {
"Also available in": "Auch verfügbar in",
+ "Also available in:": "Auch verfügbar in:",
"Archive": "Archiv",
"Categories": "Kategorien",
"LANGUAGE": "Deutsch",
+ "More posts about %s": "Weitere Einträge über %s",
"More posts about": "Weitere Einträge über",
"Newer posts": "Neuere Einträge",
"Next post": "Nächster Eintrag",
"Older posts": "Ältere Einträge",
"Original site": "Original-Seite",
"Posted": "Veröffentlicht",
+ "Posted:": "Veröffentlicht:",
"Posts about %s": "Einträge über %s",
"Posts for year %s": "Einträge aus dem Jahr %s",
"Posts for {month} {year}": "Einträge aus {month} {year}",
@@ -21,5 +24,6 @@ MESSAGES = {
"Source": "Source",
"Tags and Categories": "Tags und Kategorien",
"Tags": "Tags",
- "old posts page %d": "Vorherige Einträge %d",
+ "old posts, page %d": "Vorherige Einträge, Seite %d",
+ "page %d": "Seite %d",
}
diff --git a/nikola/data/themes/base/messages/messages_el.py b/nikola/data/themes/base/messages/messages_el.py
index a1745fa..710558b 100644
--- a/nikola/data/themes/base/messages/messages_el.py
+++ b/nikola/data/themes/base/messages/messages_el.py
@@ -3,15 +3,18 @@ from __future__ import unicode_literals
MESSAGES = {
"Also available in": "Διαθέσιμο και στα",
+ "Also available in:": "Διαθέσιμο και στα:",
"Archive": "Αρχείο",
"Categories": "Κατηγορίες",
"LANGUAGE": "Ελληνικά",
+ "More posts about %s": "Περισσότερες αναρτήσεις για %s",
"More posts about": "Περισσότερες αναρτήσεις για",
"Newer posts": "Νεότερες αναρτήσεις",
"Next post": "Επόμενη ανάρτηση",
"Older posts": "Παλαιότερες αναρτήσεις",
"Original site": "Ιστοσελίδα αρχικής ανάρτησης",
"Posted": "Αναρτήθηκε",
+ "Posted:": "Αναρτήθηκε:",
"Posts about %s": "Αναρτήσεις για %s",
"Posts for year %s": "Αναρτήσεις για το έτος %s",
"Posts for {month} {year}": "Αναρτήσεις για τον {month} του {year}",
@@ -19,7 +22,8 @@ MESSAGES = {
"Read in English": "Διαβάστε στα Ελληνικά",
"Read more": "Διαβάστε περισσότερα",
"Source": "Πηγαίος κώδικας",
- "Tags and Categories": "",
+ "Tags and Categories": "Ετικέτες και κατηγορίες",
"Tags": "Ετικέτες",
- "old posts page %d": "σελίδα παλαιότερων αναρτήσεων %d",
+ "old posts, page %d": "σελίδα παλαιότερων αναρτήσεων %d",
+ "page %d": "σελίδα %d",
}
diff --git a/nikola/data/themes/base/messages/messages_en.py b/nikola/data/themes/base/messages/messages_en.py
index 1e695ac..021f5e7 100644
--- a/nikola/data/themes/base/messages/messages_en.py
+++ b/nikola/data/themes/base/messages/messages_en.py
@@ -3,17 +3,18 @@ from __future__ import unicode_literals
MESSAGES = {
"Also available in": "Also available in",
+ "Also available in:": "Also available in:",
"Archive": "Archive",
"Categories": "Categories",
"LANGUAGE": "English",
+ "More posts about %s": "More posts about %s",
"More posts about": "More posts about",
"Newer posts": "Newer posts",
"Next post": "Next post",
- "No content": "",
- "No title": "",
"Older posts": "Older posts",
"Original site": "Original site",
"Posted": "Posted",
+ "Posted:": "Posted:",
"Posts about %s": "Posts about %s",
"Posts for year %s": "Posts for year %s",
"Posts for {month} {year}": "Posts for {month} {year}",
@@ -23,5 +24,6 @@ MESSAGES = {
"Source": "Source",
"Tags and Categories": "Tags and Categories",
"Tags": "Tags",
- "old posts page %d": "old posts page %d",
+ "old posts, page %d": "old posts, page %d",
+ "page %d": "page %d",
}
diff --git a/nikola/data/themes/base/messages/messages_eo.py b/nikola/data/themes/base/messages/messages_eo.py
index 50bd25a..fdbea88 100644
--- a/nikola/data/themes/base/messages/messages_eo.py
+++ b/nikola/data/themes/base/messages/messages_eo.py
@@ -3,15 +3,18 @@ from __future__ import unicode_literals
MESSAGES = {
"Also available in": "Ankaŭ disponebla en",
+ "Also available in:": "Ankaŭ disponebla en:",
"Archive": "Arĥivo",
"Categories": "Kategorioj",
"LANGUAGE": "Anglalingve",
- "More posts about": "Pli artikoloj pri...",
+ "More posts about %s": "Pli artikoloj pri %s",
+ "More posts about": "Pli artikoloj pri",
"Newer posts": "Pli novaj artikoloj",
"Next post": "Venonta artikolo",
"Older posts": "Pli malnovaj artikoloj",
"Original site": "Originala interretejo",
"Posted": "Skribita",
+ "Posted:": "Skribita:",
"Posts about %s": "Artikoloj pri %s",
"Posts for year %s": "Artikoloj de la jaro %s",
"Posts for {month} {year}": "Artikoloj skribitaj en {month} {year}",
@@ -21,5 +24,6 @@ MESSAGES = {
"Source": "Fonto",
"Tags and Categories": "Etikedoj kaj Kategorioj",
"Tags": "Etikedoj",
- "old posts page %d": "paĝo de malnovaj artikoloj %d",
+ "old posts, page %d": "paĝo de malnovaj artikoloj %d",
+ "page %d": "paĝo %d",
}
diff --git a/nikola/data/themes/base/messages/messages_es.py b/nikola/data/themes/base/messages/messages_es.py
index 79ffac6..6c48fb9 100644
--- a/nikola/data/themes/base/messages/messages_es.py
+++ b/nikola/data/themes/base/messages/messages_es.py
@@ -3,15 +3,18 @@ from __future__ import unicode_literals
MESSAGES = {
"Also available in": "También disponible en",
+ "Also available in:": "También disponible en:",
"Archive": "Archivo",
"Categories": "Categorías",
"LANGUAGE": "Español",
+ "More posts about %s": "Más posts sobre %s",
"More posts about": "Más posts sobre",
"Newer posts": "Posts posteriores",
"Next post": "Siguiente post",
"Older posts": "Posts anteriores",
"Original site": "Sitio original",
"Posted": "Publicado",
+ "Posted:": "Publicado:",
"Posts about %s": "Posts sobre %s",
"Posts for year %s": "Posts del año %s",
"Posts for {month} {year}": "Posts de {month} {year}",
@@ -21,5 +24,6 @@ MESSAGES = {
"Source": "Código",
"Tags and Categories": "Tags y Categorías",
"Tags": "Tags",
- "old posts page %d": "posts antiguos página %d",
+ "old posts, page %d": "posts antiguos, página %d",
+ "page %d": "página %d",
}
diff --git a/nikola/data/themes/base/messages/messages_et.py b/nikola/data/themes/base/messages/messages_et.py
new file mode 100644
index 0000000..314f3b8
--- /dev/null
+++ b/nikola/data/themes/base/messages/messages_et.py
@@ -0,0 +1,29 @@
+# -*- encoding:utf-8 -*-
+from __future__ import unicode_literals
+
+MESSAGES = {
+ "Also available in": "Saadaval ka",
+ "Also available in:": "Saadaval ka:",
+ "Archive": "Arhiiv",
+ "Categories": "Kategooriad",
+ "LANGUAGE": "Eesti",
+ "More posts about %s": "Veel postitusi %s kohta",
+ "More posts about": "Veel postitusi kohta",
+ "Newer posts": "Uued postitused",
+ "Next post": "Järgmine postitus",
+ "Older posts": "Vanemad postitused",
+ "Original site": "Algallikas",
+ "Posted": "Postitatud",
+ "Posted:": "Postitatud:",
+ "Posts about %s": "Postitused %s kohta",
+ "Posts for year %s": "Postitused aastast %s",
+ "Posts for {month} {year}": "Postitused {year} aasta kuust {month} ",
+ "Previous post": "Eelmine postitus",
+ "Read in English": "Loe eesti keeles",
+ "Read more": "Loe veel",
+ "Source": "Lähtekood",
+ "Tags and Categories": "Sildid ja kategooriad",
+ "Tags": "Märksõnad",
+ "old posts, page %d": "vanade postituste, leht %d",
+ "page %d": "leht %d",
+}
diff --git a/nikola/data/themes/base/messages/messages_eu.py b/nikola/data/themes/base/messages/messages_eu.py
new file mode 100644
index 0000000..18d7575
--- /dev/null
+++ b/nikola/data/themes/base/messages/messages_eu.py
@@ -0,0 +1,29 @@
+# -*- encoding:utf-8 -*-
+from __future__ import unicode_literals
+
+MESSAGES = {
+ "Also available in": "Eskuragarria hemen ere",
+ "Also available in:": "Eskuragarria hemen ere:",
+ "Archive": "Artxiboa",
+ "Categories": "Kategoriak",
+ "LANGUAGE": "Euskara",
+ "More posts about %s": "%s-ri buruzko post gehiago",
+ "More posts about": "-ri buruzko post gehiago",
+ "Newer posts": "Post berrienak",
+ "Next post": "Hurrengo posta",
+ "Older posts": "Post zaharrenak",
+ "Original site": "Jatorrizko orria",
+ "Posted": "Argitaratuta",
+ "Posted:": "Argitaratuta:",
+ "Posts about %s": "%s-ri buruzko postak",
+ "Posts for year %s": "%s. urteko postak",
+ "Posts for {month} {year}": "{year}ko {month}ren postak",
+ "Previous post": "Aurreko posta",
+ "Read in English": "Euskaraz irakurri",
+ "Read more": "Irakurri gehiago",
+ "Source": "Iturria",
+ "Tags and Categories": "Etiketak eta Kategoriak",
+ "Tags": "Etiketak",
+ "old posts, page %d": "Post zaharren, orria %d",
+ "page %d": "orria %d",
+}
diff --git a/nikola/data/themes/base/messages/messages_fa.py b/nikola/data/themes/base/messages/messages_fa.py
index 786893c..bd278ca 100644
--- a/nikola/data/themes/base/messages/messages_fa.py
+++ b/nikola/data/themes/base/messages/messages_fa.py
@@ -3,15 +3,18 @@ from __future__ import unicode_literals
MESSAGES = {
"Also available in": "همچنین قابل دسترس از",
+ "Also available in:": "همچنین قابل دسترس از:",
"Archive": "آرشیو",
"Categories": "دسته‌ها",
"LANGUAGE": "فارسی",
+ "More posts about %s": "ارسال‌های بیشتر دربارهٔ%s",
"More posts about": "ارسال‌های بیشتر دربارهٔ",
"Newer posts": "ارسال‌های جدید‌تر",
"Next post": "ارسال بعدی",
"Older posts": "پست‌های قدیمی‌تر",
"Original site": "سایت اصلی",
"Posted": "ارسال شده",
+ "Posted:": "ارسال شده:",
"Posts about %s": "ارسال‌ها دربارهٔ %s",
"Posts for year %s": "ارسال‌ها برای سال %s",
"Posts for {month} {year}": "ارسال برای {month} {year}",
@@ -21,5 +24,6 @@ MESSAGES = {
"Source": "منبع",
"Tags and Categories": "برچسب‌ها و دسته‌ها",
"Tags": "برچسب‌ها",
- "old posts page %d": "صفحهٔ ارسال‌های قدیمی %d",
+ "old posts, page %d": "صفحهٔ ارسال‌های قدیمی %d",
+ "page %d": "",
}
diff --git a/nikola/data/themes/base/messages/messages_fi.py b/nikola/data/themes/base/messages/messages_fi.py
index ca64919..b24ee2c 100644
--- a/nikola/data/themes/base/messages/messages_fi.py
+++ b/nikola/data/themes/base/messages/messages_fi.py
@@ -3,15 +3,18 @@ from __future__ import unicode_literals
MESSAGES = {
"Also available in": "Saatavilla myös",
+ "Also available in:": "Saatavilla myös:",
"Archive": "Arkisto",
"Categories": "Kategoriat",
"LANGUAGE": "Suomi",
+ "More posts about %s": "Lisää postauksia aiheesta %s",
"More posts about": "Lisää postauksia aiheesta",
"Newer posts": "Uudempia postauksia",
"Next post": "Seuraava postaus",
"Older posts": "Vanhempia postauksia",
"Original site": "Alkuperäinen sivusto",
"Posted": "Postattu",
+ "Posted:": "Postattu:",
"Posts about %s": "Postauksia aiheesta %s",
"Posts for year %s": "Postauksia vuodelta %s",
"Posts for {month} {year}": "Postauksia ajalle {month} {year}",
@@ -21,5 +24,6 @@ MESSAGES = {
"Source": "Lähde",
"Tags and Categories": "Tagit ja kategoriat",
"Tags": "Tagit",
- "old posts page %d": "vanhojen postauksien sivu %d",
+ "old posts, page %d": "vanhojen postauksien, sivu %d",
+ "page %d": "sivu %d",
}
diff --git a/nikola/data/themes/base/messages/messages_fr.py b/nikola/data/themes/base/messages/messages_fr.py
index 45c7474..ad4aea0 100644
--- a/nikola/data/themes/base/messages/messages_fr.py
+++ b/nikola/data/themes/base/messages/messages_fr.py
@@ -2,24 +2,28 @@
from __future__ import unicode_literals
MESSAGES = {
- "Also available in": "Disponible aussi en",
+ "Also available in": "Egalement disponible en",
+ "Also available in:": "Egalement disponible en:",
"Archive": "Archives",
"Categories": "Catégories",
"LANGUAGE": "Français",
- "More posts about": "Plus de billets sur",
+ "More posts about %s": "Plus d'articles sur %s",
+ "More posts about": "Plus d'articles sur",
"Newer posts": "Billets récents",
- "Next post": "Billet suivant",
- "Older posts": "Anciens billets",
+ "Next post": "Article suivant",
+ "Older posts": "Anciens articles",
"Original site": "Site d'origine",
"Posted": "Publié",
- "Posts about %s": "Billets sur %s",
- "Posts for year %s": "Billets de l'année %s",
- "Posts for {month} {year}": "Billets de {month} {year}",
- "Previous post": "Billet précédent",
+ "Posted:": "Publié:",
+ "Posts about %s": "Articles sur %s",
+ "Posts for year %s": "Articles de l'année %s",
+ "Posts for {month} {year}": "Articles de {month} {year}",
+ "Previous post": "Article précédent",
"Read in English": "Lire en français",
"Read more": "Lire la suite",
"Source": "Source",
"Tags and Categories": "Étiquettes et catégories",
"Tags": "Étiquettes",
- "old posts page %d": "anciens billets page %d",
+ "old posts, page %d": "anciens articles, page %d",
+ "page %d": "page %d",
}
diff --git a/nikola/data/themes/base/messages/messages_hr.py b/nikola/data/themes/base/messages/messages_hr.py
index 420159d..ad74078 100644
--- a/nikola/data/themes/base/messages/messages_hr.py
+++ b/nikola/data/themes/base/messages/messages_hr.py
@@ -3,15 +3,18 @@ from __future__ import unicode_literals
MESSAGES = {
"Also available in": "Također dostupno i u",
+ "Also available in:": "Također dostupno i u:",
"Archive": "Arhiva",
- "Categories": "",
+ "Categories": "Kategorije",
"LANGUAGE": "hrvatski",
+ "More posts about %s": "Više postova o %s",
"More posts about": "Više postova o",
"Newer posts": "Noviji postovi",
"Next post": "Sljedeći post",
"Older posts": "Stariji postovi",
"Original site": "Izvorna stranica",
"Posted": "Objavljeno",
+ "Posted:": "Objavljeno:",
"Posts about %s": "Postovi o %s",
"Posts for year %s": "Postovi za godinu %s",
"Posts for {month} {year}": "Postovi za {month} {year}",
@@ -19,7 +22,8 @@ MESSAGES = {
"Read in English": "Čitaj na hrvatskom",
"Read more": "Čitaj dalje",
"Source": "Izvor",
- "Tags and Categories": "",
+ "Tags and Categories": "Tagovi i kategorije",
"Tags": "Tagovi",
- "old posts page %d": "stari postovi stranice %d",
+ "old posts, page %d": "stari postovi, stranice %d",
+ "page %d": "stranice %d",
}
diff --git a/nikola/data/themes/base/messages/messages_it.py b/nikola/data/themes/base/messages/messages_it.py
index b460f22..912342e 100644
--- a/nikola/data/themes/base/messages/messages_it.py
+++ b/nikola/data/themes/base/messages/messages_it.py
@@ -3,15 +3,18 @@ from __future__ import unicode_literals
MESSAGES = {
"Also available in": "Anche disponibile in",
+ "Also available in:": "Anche disponibile in:",
"Archive": "Archivio",
"Categories": "Categorie",
"LANGUAGE": "Italiano",
+ "More posts about %s": "Altri articoli collegati %s",
"More posts about": "Altri articoli collegati",
"Newer posts": "Articoli recenti",
"Next post": "Articolo successivo",
"Older posts": "Articoli precedenti",
"Original site": "Sito originale",
"Posted": "Pubblicato",
+ "Posted:": "Pubblicato:",
"Posts about %s": "Articoli su %s",
"Posts for year %s": "Articoli per l'anno %s",
"Posts for {month} {year}": "Articoli per {month} {year}",
@@ -21,5 +24,6 @@ MESSAGES = {
"Source": "Sorgente",
"Tags and Categories": "Tags e Categorie",
"Tags": "Tags",
- "old posts page %d": "pagina dei vecchi articoli %d",
+ "old posts, page %d": "pagina dei vecchi articoli %d",
+ "page %d": "pagina %d",
}
diff --git a/nikola/data/themes/base/messages/messages_ja.py b/nikola/data/themes/base/messages/messages_ja.py
index 4a238cc..1bdf168 100644
--- a/nikola/data/themes/base/messages/messages_ja.py
+++ b/nikola/data/themes/base/messages/messages_ja.py
@@ -3,15 +3,18 @@ from __future__ import unicode_literals
MESSAGES = {
"Also available in": "他の言語で読む",
+ "Also available in:": "他の言語で読む:",
"Archive": "過去の記事",
- "Categories": "",
+ "Categories": "カテゴリー",
"LANGUAGE": "日本語",
- "More posts about": "タグ",
+ "More posts about %s": "タグ: %s",
+ "More posts about": "タグ:",
"Newer posts": "新しい記事",
"Next post": "次の記事",
"Older posts": "過去の記事",
"Original site": "元のサイト",
"Posted": "投稿日時",
+ "Posted:": "投稿日時:",
"Posts about %s": "%sについての記事",
"Posts for year %s": "%s年の記事",
"Posts for {month} {year}": "{year}年{month}月の記事",
@@ -19,7 +22,8 @@ MESSAGES = {
"Read in English": "日本語で読む",
"Read more": "続きを読む",
"Source": "ソース",
- "Tags and Categories": "",
+ "Tags and Categories": "タグとカテゴリー",
"Tags": "タグ",
- "old posts page %d": "前の記事 %dページ目",
+ "old posts, page %d": "前の記事 %dページ目",
+ "page %d": "",
}
diff --git a/nikola/data/themes/base/messages/messages_nb.py b/nikola/data/themes/base/messages/messages_nb.py
new file mode 100644
index 0000000..154e329
--- /dev/null
+++ b/nikola/data/themes/base/messages/messages_nb.py
@@ -0,0 +1,29 @@
+# -*- encoding:utf-8 -*-
+from __future__ import unicode_literals
+
+MESSAGES = {
+ "Also available in": "Også tilgjengelig på",
+ "Also available in:": "Også tilgjengelig på:",
+ "Archive": "Arkiv",
+ "Categories": "Kategorier",
+ "LANGUAGE": "norsk",
+ "More posts about %s": "Flere innlegg om %s",
+ "More posts about": "Flere innlegg om",
+ "Newer posts": "Nyere innlegg",
+ "Next post": "Neste innlegg",
+ "Older posts": "Eldre innlegg",
+ "Original site": "Opprinnelig side",
+ "Posted": "Publisert",
+ "Posted:": "Publisert:",
+ "Posts about %s": "Innlegg om %s",
+ "Posts for year %s": "Innlegg fra %s",
+ "Posts for {month} {year}": "Innlegg fra {month} {year}",
+ "Previous post": "Forrige innlegg",
+ "Read in English": "Les på norsk",
+ "Read more": "Les mer",
+ "Source": "Kilde",
+ "Tags and Categories": "Merker og kategorier",
+ "Tags": "Merker",
+ "old posts, page %d": "eldre innlegg, side %d",
+ "page %d": "side %d",
+}
diff --git a/nikola/data/themes/base/messages/messages_nl.py b/nikola/data/themes/base/messages/messages_nl.py
index a2da822..887e85f 100644
--- a/nikola/data/themes/base/messages/messages_nl.py
+++ b/nikola/data/themes/base/messages/messages_nl.py
@@ -3,15 +3,18 @@ from __future__ import unicode_literals
MESSAGES = {
"Also available in": "Ook beschikbaar in",
+ "Also available in:": "Ook beschikbaar in:",
"Archive": "Archief",
"Categories": "Categorieën",
"LANGUAGE": "Nederlands",
+ "More posts about %s": "Meer berichten over %s",
"More posts about": "Meer berichten over",
"Newer posts": "Nieuwere berichten",
"Next post": "Volgend bericht",
"Older posts": "Oudere berichten",
"Original site": "Originele site",
"Posted": "Geplaatst",
+ "Posted:": "Geplaatst:",
"Posts about %s": "Berichten over %s",
"Posts for year %s": "Berichten voor het jaar %s",
"Posts for {month} {year}": "Berichten voor {month} {year}",
@@ -21,5 +24,6 @@ MESSAGES = {
"Source": "Bron",
"Tags and Categories": "Tags en Categorieën",
"Tags": "Tags",
- "old posts page %d": "oude berichten pagina %d",
+ "old posts, page %d": "oude berichten, pagina %d",
+ "page %d": "pagina %d",
}
diff --git a/nikola/data/themes/base/messages/messages_pl.py b/nikola/data/themes/base/messages/messages_pl.py
index cf5c51c..352b0ed 100644
--- a/nikola/data/themes/base/messages/messages_pl.py
+++ b/nikola/data/themes/base/messages/messages_pl.py
@@ -2,16 +2,19 @@
from __future__ import unicode_literals
MESSAGES = {
- "Also available in": "Również dostępny w",
+ "Also available in": "Również dostępny w językach",
+ "Also available in:": "Również dostępny w językach:",
"Archive": "Archiwum",
"Categories": "Kategorie",
"LANGUAGE": "polski",
+ "More posts about %s": "Więcej postów o %s",
"More posts about": "Więcej postów o",
"Newer posts": "Nowsze posty",
"Next post": "Następny post",
"Older posts": "Starsze posty",
"Original site": "Oryginalna strona",
- "Posted": "Opublikowany",
+ "Posted": "Opublikowano",
+ "Posted:": "Opublikowano:",
"Posts about %s": "Posty o %s",
"Posts for year %s": "Posty z roku %s",
"Posts for {month} {year}": "Posty z {month} {year}",
@@ -21,5 +24,6 @@ MESSAGES = {
"Source": "Źródło",
"Tags and Categories": "Tagi i Kategorie",
"Tags": "Tags",
- "old posts page %d": "stare posty, strona %d",
+ "old posts, page %d": "stare posty, strona %d",
+ "page %d": "strona %d",
}
diff --git a/nikola/data/themes/base/messages/messages_pt_br.py b/nikola/data/themes/base/messages/messages_pt_br.py
index ebf642a..1283a2a 100644
--- a/nikola/data/themes/base/messages/messages_pt_br.py
+++ b/nikola/data/themes/base/messages/messages_pt_br.py
@@ -3,15 +3,18 @@ from __future__ import unicode_literals
MESSAGES = {
"Also available in": "Também disponível em",
+ "Also available in:": "Também disponível em:",
"Archive": "Arquivo",
"Categories": "Categorias",
"LANGUAGE": "Português",
+ "More posts about %s": "Mais posts sobre %s",
"More posts about": "Mais posts sobre",
"Newer posts": "Posts mais recentes",
"Next post": "Próximo post",
"Older posts": "Posts mais antigos",
"Original site": "Site original",
"Posted": "Publicado",
+ "Posted:": "Publicado:",
"Posts about %s": "Posts sobre %s",
"Posts for year %s": "Posts do ano %s",
"Posts for {month} {year}": "Posts de {month} {year}",
@@ -21,5 +24,6 @@ MESSAGES = {
"Source": "Código",
"Tags and Categories": "Tags e Categorias",
"Tags": "Tags",
- "old posts page %d": "Posts antigos página %d",
+ "old posts, page %d": "Posts antigos, página %d",
+ "page %d": "página %d",
}
diff --git a/nikola/data/themes/base/messages/messages_ru.py b/nikola/data/themes/base/messages/messages_ru.py
index 44ce1f2..3462292 100644
--- a/nikola/data/themes/base/messages/messages_ru.py
+++ b/nikola/data/themes/base/messages/messages_ru.py
@@ -3,15 +3,18 @@ from __future__ import unicode_literals
MESSAGES = {
"Also available in": "Также доступно на",
+ "Also available in:": "Также доступно на:",
"Archive": "Архив",
"Categories": "Категории",
"LANGUAGE": "Русский",
+ "More posts about %s": "Больше записей о %s",
"More posts about": "Больше записей о",
"Newer posts": "Новые записи",
"Next post": "Следующая запись",
"Older posts": "Старые записи",
"Original site": "Оригинальный сайт",
"Posted": "Опубликовано",
+ "Posted:": "Опубликовано:",
"Posts about %s": "Записи о %s",
"Posts for year %s": "Записи за %s год",
"Posts for {month} {year}": "Записи за {month} {year}",
@@ -21,5 +24,6 @@ MESSAGES = {
"Source": "Источник",
"Tags and Categories": "Тэги и категории",
"Tags": "Тэги",
- "old posts page %d": "%d страница со старыми записями",
+ "old posts, page %d": "%d страница со старыми записями",
+ "page %d": "%d страница",
}
diff --git a/nikola/data/themes/base/messages/messages_sl.py b/nikola/data/themes/base/messages/messages_sl.py
index bad3327..817bcee 100644
--- a/nikola/data/themes/base/messages/messages_sl.py
+++ b/nikola/data/themes/base/messages/messages_sl.py
@@ -3,15 +3,18 @@ from __future__ import unicode_literals
MESSAGES = {
"Also available in": "Na voljo tudi v",
+ "Also available in:": "Na voljo tudi v:",
"Archive": "Arhiv",
"Categories": "Kategorije",
"LANGUAGE": "Slovenščina",
+ "More posts about %s": "Več objav o %s",
"More posts about": "Več objav o",
"Newer posts": "Novejše objave",
"Next post": "Naslednja objava",
"Older posts": "Starejše objave",
"Original site": "Izvorna spletna stran",
"Posted": "Objavljeno",
+ "Posted:": "Objavljeno:",
"Posts about %s": "Objave o %s",
"Posts for year %s": "Objave za leto %s",
"Posts for {month} {year}": "Objave za {month} {year}",
@@ -21,5 +24,6 @@ MESSAGES = {
"Source": "Izvor",
"Tags and Categories": "Značke in kategorije",
"Tags": "Značke",
- "old posts page %d": "stare objave, stran %d",
+ "old posts, page %d": "stare objave, stran %d",
+ "page %d": "stran %d",
}
diff --git a/nikola/data/themes/base/messages/messages_tr.py b/nikola/data/themes/base/messages/messages_tr.py
new file mode 120000
index 0000000..ad92768
--- /dev/null
+++ b/nikola/data/themes/base/messages/messages_tr.py
@@ -0,0 +1 @@
+messages_tr_tr.py \ No newline at end of file
diff --git a/nikola/data/themes/base/messages/messages_tr_tr.py b/nikola/data/themes/base/messages/messages_tr_tr.py
index 7cf0e9f..633f057 100644
--- a/nikola/data/themes/base/messages/messages_tr_tr.py
+++ b/nikola/data/themes/base/messages/messages_tr_tr.py
@@ -2,16 +2,19 @@
from __future__ import unicode_literals
MESSAGES = {
- "Also available in": "Şu dilde de mevcut:",
+ "Also available in": "Şu dilde de mevcut",
+ "Also available in:": "Şu dilde de mevcut:",
"Archive": "Arşiv",
"Categories": "Kategoriler",
"LANGUAGE": "Türkçe",
- "More posts about": "ilgili diğer yazılar",
+ "More posts about %s": "%s ilgili diğer yazılar",
+ "More posts about": " ilgili diğer yazılar",
"Newer posts": "Daha yeni yazılar",
"Next post": "Sonraki yazı",
"Older posts": "Daha eski yazılar",
"Original site": "Orjinal web sayfası",
"Posted": "Yayın tarihi",
+ "Posted:": "Yayın tarihi:",
"Posts about %s": "%s ile ilgili yazılar",
"Posts for year %s": "%s yılındaki yazılar",
"Posts for {month} {year}": "{month} {year} göre yazılar",
@@ -21,5 +24,6 @@ MESSAGES = {
"Source": "Kaynak",
"Tags and Categories": "Etiketler ve Kategoriler",
"Tags": "Etiketler",
- "old posts page %d": "eski yazılar sayfa %d",
+ "old posts, page %d": "eski yazılar, sayfa %d",
+ "page %d": "sayfa %d",
}
diff --git a/nikola/data/themes/base/messages/messages_ur.py b/nikola/data/themes/base/messages/messages_ur.py
new file mode 100644
index 0000000..d9c2f2b
--- /dev/null
+++ b/nikola/data/themes/base/messages/messages_ur.py
@@ -0,0 +1,29 @@
+# -*- encoding:utf-8 -*-
+from __future__ import unicode_literals
+
+MESSAGES = {
+ "Also available in": "ان زبانوں میں بھی دستیاب",
+ "Also available in:": "ان زبانوں میں بھی دستیاب:",
+ "Archive": "آرکائیو",
+ "Categories": "زمرے",
+ "LANGUAGE": "اردو",
+ "More posts about %s": "%s کے بارے میں مزید تحاریر",
+ "More posts about": " کے بارے میں مزید تحاریر",
+ "Newer posts": "نئی تحاریر",
+ "Next post": "اگلی تحریر",
+ "Older posts": "پرانی تحاریر",
+ "Original site": "اصلی سائٹ",
+ "Posted": "اشاعت",
+ "Posted:": "اشاعت:",
+ "Posts about %s": "%s کے بارے میں تحاریر",
+ "Posts for year %s": "سال %s کی تحاریر",
+ "Posts for {month} {year}": "{month} {year} کی تحاریر",
+ "Previous post": "پچھلی تحریر",
+ "Read in English": "اردو میں پڑھیے",
+ "Read more": "مزید پڑھیے",
+ "Source": "سورس",
+ "Tags and Categories": "ٹیگز اور زمرے",
+ "Tags": "ٹیگز",
+ "old posts, page %d": "پرانی تحاریر صفحہ %d",
+ "page %d": "",
+}
diff --git a/nikola/data/themes/base/messages/messages_zh_cn.py b/nikola/data/themes/base/messages/messages_zh_cn.py
index fc79313..cb9a2f7 100644
--- a/nikola/data/themes/base/messages/messages_zh_cn.py
+++ b/nikola/data/themes/base/messages/messages_zh_cn.py
@@ -3,15 +3,18 @@ from __future__ import unicode_literals
MESSAGES = {
"Also available in": "其他语言版本",
+ "Also available in:": "其他语言版本:",
"Archive": "文章存档",
- "Categories": "",
+ "Categories": "分类",
"LANGUAGE": "简体中文",
+ "More posts about %s": "更多相关文章: %s",
"More posts about": "更多相关文章:",
"Newer posts": "新一篇",
"Next post": "后一篇",
"Older posts": "旧一篇",
"Original site": "原文地址",
"Posted": "发表于",
+ "Posted:": "发表于:",
"Posts about %s": "文章分类:%s",
"Posts for year %s": "%s年文章",
"Posts for {month} {year}": "{year}年{month}月文章",
@@ -19,7 +22,8 @@ MESSAGES = {
"Read in English": "中文版",
"Read more": "更多",
"Source": "源代码",
- "Tags and Categories": "",
+ "Tags and Categories": "标签和分类",
"Tags": "标签",
- "old posts page %d": "旧文章页 %d",
+ "old posts, page %d": "旧文章页 %d",
+ "page %d": "",
}
diff --git a/nikola/data/themes/base/templates/base.tmpl b/nikola/data/themes/base/templates/base.tmpl
index 31c1747..7c6cc35 100644
--- a/nikola/data/themes/base/templates/base.tmpl
+++ b/nikola/data/themes/base/templates/base.tmpl
@@ -21,7 +21,7 @@ lang="${lang}">
<%block name="belowtitle">
%if len(translations) > 1:
<small>
- ${(messages("Also available in"))}:&nbsp;
+ ${messages("Also available in:")}&nbsp;
${base.html_translations()}
</small>
%endif
diff --git a/nikola/data/themes/base/templates/base_helper.tmpl b/nikola/data/themes/base/templates/base_helper.tmpl
index ac1dea3..880a998 100644
--- a/nikola/data/themes/base/templates/base_helper.tmpl
+++ b/nikola/data/themes/base/templates/base_helper.tmpl
@@ -21,6 +21,7 @@
<link href="/assets/css/custom.css" rel="stylesheet" type="text/css">
%endif
%endif
+ <link rel="canonical" href="${abs_link(permalink)}">
<!--[if lt IE 9]>
<script src="http://html5shim.googlecode.com/svn/trunk/html5.js" type="text/javascript"></script>
<![endif]-->
@@ -49,7 +50,7 @@
</%def>
<%def name="html_social()">
- ${social_buttons_code}
+ ${social_buttons_code}
</%def>
<!--FIXME: remove in v7 -->
@@ -64,7 +65,7 @@
<ul>
%for suburl, text in url:
% if rel_link(permalink, suburl) == "#":
- <li class="active"><a href="${suburl}">${text}</a>
+ <li class="active"><a href="${permalink}">${text}</a>
%else:
<li><a href="${suburl}">${text}</a>
%endif
@@ -72,7 +73,7 @@
</ul>
% else:
% if rel_link(permalink, url) == "#":
- <li class="active"><a href="${url}">${text}</a>
+ <li class="active"><a href="${permalink}">${text}</a>
%else:
<li><a href="${url}">${text}</a>
%endif
@@ -84,7 +85,7 @@
<%def name="html_translations()">
%for langname in translations.keys():
%if langname != lang:
- <a href="${_link("index", None, langname)}">${messages("LANGUAGE", langname)}</a>
+ <a href="${_link("index", None, langname)}" rel="alternate" hreflang="${langname}">${messages("LANGUAGE", langname)}</a>
%endif
%endfor
</%def>
diff --git a/nikola/data/themes/base/templates/comments_helper.tmpl b/nikola/data/themes/base/templates/comments_helper.tmpl
index e74a146..d3a2704 100644
--- a/nikola/data/themes/base/templates/comments_helper.tmpl
+++ b/nikola/data/themes/base/templates/comments_helper.tmpl
@@ -5,6 +5,8 @@
<%namespace name="intensedebate" file="intensedebate_helper.tmpl"/>
<%namespace name="moot" file="moot_helper.tmpl"/>
<%namespace name="googleplus" file="googleplus_helper.tmpl"/>
+<%namespace name="facebook" file="facebook_helper.tmpl"/>
+<%namespace name="isso" file="isso_helper.tmpl"/>
<%def name="comment_form(url, title, identifier)">
%if comment_system == 'disqus':
@@ -17,6 +19,10 @@
${moot.comment_form(url, title, identifier)}
% elif comment_system == 'googleplus':
${googleplus.comment_form(url, title, identifier)}
+ % elif comment_system == 'facebook':
+ ${facebook.comment_form(url, title, identifier)}
+ % elif comment_system == 'isso':
+ ${isso.comment_form(url, title, identifier)}
%endif
</%def>
@@ -31,6 +37,10 @@
${moot.comment_link(link, identifier)}
% elif comment_system == 'googleplus':
${googleplus.comment_link(link, identifier)}
+ % elif comment_system == 'facebook':
+ ${facebook.comment_link(link, identifier)}
+ % elif comment_system == 'isso':
+ ${isso.comment_link(link, identifier)}
%endif
</%def>
@@ -45,5 +55,9 @@
${moot.comment_link_script()}
% elif comment_system == 'googleplus':
${googleplus.comment_link_script()}
+ % elif comment_system == 'facebook':
+ ${facebook.comment_link_script()}
+ % elif comment_system == 'isso':
+ ${isso.comment_link_script()}
%endif
</%def>
diff --git a/nikola/data/themes/base/templates/disqus_helper.tmpl b/nikola/data/themes/base/templates/disqus_helper.tmpl
index 211f27a..74187b0 100644
--- a/nikola/data/themes/base/templates/disqus_helper.tmpl
+++ b/nikola/data/themes/base/templates/disqus_helper.tmpl
@@ -9,24 +9,24 @@
<%def name="comment_form(url, title, identifier)">
%if comment_system_id:
<div id="disqus_thread"></div>
- <script type="text/javascript">
- var disqus_shortname ="${comment_system_id}";
+ <script>
+ var disqus_shortname ="${comment_system_id}",
%if url:
- var disqus_url="${url}";
+ disqus_url="${url}",
%endif
- var disqus_title=${json.dumps(title)};
- var disqus_identifier="${identifier}";
- var disqus_config = function () {
+ disqus_title=${json.dumps(title)},
+ disqus_identifier="${identifier}",
+ disqus_config = function () {
this.language = "${translations.get(lang, lang)}";
};
(function() {
- var dsq = document.createElement('script'); dsq.type = 'text/javascript'; dsq.async = true;
- dsq.src = 'http://' + disqus_shortname + '.disqus.com/embed.js';
+ var dsq = document.createElement('script'); dsq.async = true;
+ dsq.src = '//' + disqus_shortname + '.disqus.com/embed.js';
(document.getElementsByTagName('head')[0] || document.getElementsByTagName('body')[0]).appendChild(dsq);
})();
</script>
- <noscript>Please enable JavaScript to view the <a href="http://disqus.com/?ref_noscript">comments powered by Disqus.</a></noscript>
- <a href="http://disqus.com" class="dsq-brlink">Comments powered by <span class="logo-disqus">Disqus</span></a>
+ <noscript>Please enable JavaScript to view the <a href="http://disqus.com/?ref_noscript" rel="nofollow">comments powered by Disqus.</a></noscript>
+ <a href="http://disqus.com" class="dsq-brlink" rel="nofollow">Comments powered by <span class="logo-disqus">Disqus</span></a>
%endif
</%def>
@@ -40,7 +40,7 @@
<%def name="comment_link_script()">
%if comment_system_id:
- <script type="text/javascript">var disqus_shortname="${comment_system_id}";(function(){var a=document.createElement("script");a.async=true;a.type="text/javascript";a.src="http://"+disqus_shortname+".disqus.com/count.js";(document.getElementsByTagName("HEAD")[0]||document.getElementsByTagName("BODY")[0]).appendChild(a)}());</script>
+ <script>var disqus_shortname="${comment_system_id}";(function(){var a=document.createElement("script");a.async=true;a.src="//"+disqus_shortname+".disqus.com/count.js";(document.getElementsByTagName("head")[0]||document.getElementsByTagName("body")[0]).appendChild(a)}());</script>
%endif
</%def>
diff --git a/nikola/data/themes/base/templates/gallery.tmpl b/nikola/data/themes/base/templates/gallery.tmpl
index be9cc6f..e4eab27 100644
--- a/nikola/data/themes/base/templates/gallery.tmpl
+++ b/nikola/data/themes/base/templates/gallery.tmpl
@@ -6,14 +6,18 @@
<%block name="content">
${ui.bar(crumbs)}
+ %if title:
+ <h1>${title}</h1>
+ %endif
%if text:
<p>
${text}
</p>
%endif
<ul>
- % for folder in folders:
- <li><a href="${folder}"><i class="icon-folder-open"></i>&nbsp;${folder}</a></li>
+ % for folder, ftitle in folders:
+ <li><a href="${folder}"><i
+ class="icon-folder-open"></i>&nbsp;${ftitle}</a></li>
% endfor
</ul>
<ul class="thumbnails">
diff --git a/nikola/data/themes/base/templates/index.tmpl b/nikola/data/themes/base/templates/index.tmpl
index 6de79e2..1a280b0 100644
--- a/nikola/data/themes/base/templates/index.tmpl
+++ b/nikola/data/themes/base/templates/index.tmpl
@@ -4,10 +4,10 @@
<%inherit file="base.tmpl"/>
<%block name="content">
% for post in posts:
- <div class="postbox h-entry">
+ <article class="postbox h-entry post-${post.meta('type')}">
<h1 class="p-name"><a href="${post.permalink()}" class="u-url">${post.title()}</a>
<small>&nbsp;&nbsp;
- ${messages("Posted")}: <time class="published dt-published" datetime="${post.date.isoformat()}">${post.formatted_date(date_format)}</time>
+ ${messages("Posted:")} <time class="published dt-published" datetime="${post.date.isoformat()}">${post.formatted_date(date_format)}</time>
</small></h1>
<hr>
%if index_teasers:
@@ -21,7 +21,7 @@
% if not post.meta('nocomments'):
${comments.comment_link(post.permalink(), post._base_path)}
% endif
- </div>
+ </article>
% endfor
${helper.html_pager()}
${comments.comment_link_script()}
diff --git a/nikola/data/themes/base/templates/index_helper.tmpl b/nikola/data/themes/base/templates/index_helper.tmpl
index a914846..56f5127 100644..100755
--- a/nikola/data/themes/base/templates/index_helper.tmpl
+++ b/nikola/data/themes/base/templates/index_helper.tmpl
@@ -1,23 +1,25 @@
## -*- coding: utf-8 -*-
<%def name="html_pager()">
-<div>
-<ul class="pager">
- %if prevlink:
- <li class="previous">
- <a href="${prevlink}" rel="prev">&larr; ${messages("Newer posts")}</a>
- </li>
- %endif
- %if nextlink:
- <li class="next">
- <a href="${nextlink}" rel="next">${messages("Older posts")} &rarr;</a>
- </li>
- %endif
-</ul>
-</div>
+ %if prevlink or nextlink:
+ <div>
+ <ul class="pager">
+ %if prevlink:
+ <li class="previous">
+ <a href="${prevlink}" rel="prev">&larr; ${messages("Newer posts")}</a>
+ </li>
+ %endif
+ %if nextlink:
+ <li class="next">
+ <a href="${nextlink}" rel="next">${messages("Older posts")} &rarr;</a>
+ </li>
+ %endif
+ </ul>
+ </div>
+ %endif
</%def>
<%def name="mathjax_script(posts)">
%if any(post.is_mathjax for post in posts):
- <script src="/assets/js/mathjax.js" type="text/javascript"></script>
+ <script src="/assets/js/mathjax.js"></script>
%endif
</%def>
diff --git a/nikola/data/themes/base/templates/isso_helper.tmpl b/nikola/data/themes/base/templates/isso_helper.tmpl
new file mode 100644
index 0000000..8dc95f5
--- /dev/null
+++ b/nikola/data/themes/base/templates/isso_helper.tmpl
@@ -0,0 +1,20 @@
+## -*- coding: utf-8 -*-
+<%def name="comment_form(url, title, identifier)">
+ %if comment_system_id:
+ <div data-title="${title|u}" id="isso-thread"></div>
+ <script src="${comment_system_id}js/embed.min.js" data-isso="${comment_system_id}"></script>
+ %endif
+</%def>
+
+<%def name="comment_link(link, identifier)">
+ %if comment_system_id:
+ <a href="${link}#isso-thread">Comments</a>
+ %endif
+</%def>
+
+
+<%def name="comment_link_script()">
+ %if comment_system_id:
+ <script src="${comment_system_id}js/count.min.js" data-isso="${comment_system_id}"></script>
+ %endif
+</%def>
diff --git a/nikola/data/themes/base/templates/post.tmpl b/nikola/data/themes/base/templates/post.tmpl
index fd6316d..981fd97 100644
--- a/nikola/data/themes/base/templates/post.tmpl
+++ b/nikola/data/themes/base/templates/post.tmpl
@@ -7,14 +7,15 @@ ${helper.twitter_card_information(post)}
% if post.meta('keywords'):
<meta name="keywords" content="${post.meta('keywords')|h}">
% endif
+${helper.meta_translations(post)}
</%block>
<%block name="content">
- <div class="postbox">
+ <article class="postbox post-${post.meta('type')}">
<div class="h-entry" itemscope="itemscope" itemtype="http://schema.org/Article">
${helper.html_title()}
<hr>
<small>
- ${messages("Posted")}: <time class="published dt-published" datetime="${post.date.isoformat()}" itemprop="datePublished">${post.formatted_date(date_format)}</time>
+ ${messages("Posted:")} <time class="published dt-published" datetime="${post.date.isoformat()}" itemprop="datePublished">${post.formatted_date(date_format)}</time>
${helper.html_translations(post)}
${helper.html_tags(post)}
&nbsp;&nbsp;|&nbsp;&nbsp;
@@ -37,5 +38,5 @@ ${helper.twitter_card_information(post)}
${comments.comment_form(post.permalink(absolute=True), post.title(), post._base_path)}
% endif
${helper.mathjax_script(post)}
- </div>
+ </article>
</%block>
diff --git a/nikola/data/themes/base/templates/post_helper.tmpl b/nikola/data/themes/base/templates/post_helper.tmpl
index f6b0535..69784ea 100644..100755
--- a/nikola/data/themes/base/templates/post_helper.tmpl
+++ b/nikola/data/themes/base/templates/post_helper.tmpl
@@ -12,37 +12,52 @@
%for langname in translations.keys():
%if langname != lang and post.is_translation_available(langname):
&nbsp;&nbsp;|&nbsp;&nbsp;
- <a href="${post.permalink(langname)}">${messages("Read in English", langname)}</a>
+ <a href="${post.permalink(langname)}" rel="alternate" hreflang="${langname}">${messages("Read in English", langname)}</a>
%endif
%endfor
%endif
</%def>
+<%def name="meta_translations(post)">
+ %if len(translations) > 1:
+ %for langname in translations.keys():
+ %if langname != lang and post.is_translation_available(langname):
+ <link rel="alternate" hreflang="${langname}" href="${post.permalink(langname)}">
+ %endif
+ %endfor
+ %endif
+</%def>
+
+<%def name="html_list_tags(post)" buffered="True">
+ <span itemprop="keywords">
+ %for tag in post.tags:
+ <a class="tag p-category" href="${_link('tag', tag)}"><span class="badge badge-info">${tag}</span></a>
+ %endfor
+ </span>
+</%def>
<%def name="html_tags(post)">
%if post.tags:
- &nbsp;&nbsp;|&nbsp;&nbsp;${messages("More posts about")}
- <span itemprop="keywords">
- %for tag in post.tags:
- <a class="tag p-category" href="${_link('tag', tag)}"><span class="badge badge-info">${tag}</span></a>
- %endfor
- </span>
+ &nbsp;&nbsp;|&nbsp;&nbsp;
+ ${formatmsg(messages("More posts about %s"), html_list_tags(post))}
%endif
</%def>
<%def name="html_pager(post)">
- <ul class="pager">
- %if post.prev_post:
- <li class="previous">
- <a href="${post.prev_post.permalink()}" rel="prev">&larr; ${messages("Previous post")}</a>
- </li>
- %endif
- %if post.next_post:
- <li class="next">
- <a href="${post.next_post.permalink()}" rel="next">${messages("Next post")} &rarr;</a>
- </li>
+ %if post.prev_post or post.next_post:
+ <ul class="pager">
+ %if post.prev_post:
+ <li class="previous">
+ <a href="${post.prev_post.permalink()}" rel="prev">&larr; ${messages("Previous post")}</a>
+ </li>
+ %endif
+ %if post.next_post:
+ <li class="next">
+ <a href="${post.next_post.permalink()}" rel="next">${messages("Next post")} &rarr;</a>
+ </li>
+ %endif
+ </ul>
%endif
- </ul>
</%def>
<%def name="twitter_card_information(post)">
diff --git a/nikola/data/themes/base/templates/tagindex.tmpl b/nikola/data/themes/base/templates/tagindex.tmpl
new file mode 100644
index 0000000..9dda70a
--- /dev/null
+++ b/nikola/data/themes/base/templates/tagindex.tmpl
@@ -0,0 +1,2 @@
+## -*- coding: utf-8 -*-
+<%inherit file="index.tmpl"/>
diff --git a/nikola/data/themes/bootstrap/assets/css/theme.css b/nikola/data/themes/bootstrap/assets/css/theme.css
index 2ff1a80..952073f 100644
--- a/nikola/data/themes/bootstrap/assets/css/theme.css
+++ b/nikola/data/themes/bootstrap/assets/css/theme.css
@@ -84,4 +84,20 @@ pre, pre code {
white-space: pre;
word-wrap: normal;
overflow: auto;
-} \ No newline at end of file
+}
+
+article.post-micro {
+ font-family: Georgia, 'Times New Roman', Times, serif;
+ font-size: 1.5em;
+}
+
+/* fix anchors for headers */
+h1, h2, h3 {
+ margin-top: -40px;
+ padding-top: 60px;
+}
+
+h4, h5, h6 {
+ margin-top: -50px;
+ padding-top: 60px;
+}
diff --git a/nikola/data/themes/bootstrap/templates/bootstrap_helper.tmpl b/nikola/data/themes/bootstrap/templates/bootstrap_helper.tmpl
index 763ac20..f0d1986 100644
--- a/nikola/data/themes/bootstrap/templates/bootstrap_helper.tmpl
+++ b/nikola/data/themes/bootstrap/templates/bootstrap_helper.tmpl
@@ -29,6 +29,7 @@
<link href="/assets/css/custom.css" rel="stylesheet" type="text/css">
%endif
%endif
+ <link rel="canonical" href="${abs_link(permalink)}">
<!--[if lt IE 9]>
<script src="http://html5shim.googlecode.com/svn/trunk/html5.js" type="text/javascript"></script>
<![endif]-->
@@ -79,7 +80,7 @@
<ul class="dropdown-menu">
%for suburl, text in url:
% if rel_link(permalink, suburl) == "#":
- <li class="active"><a href="${suburl}">${text}</a>
+ <li class="active"><a href="${permalink}">${text}</a>
%else:
<li><a href="${suburl}">${text}</a>
%endif
@@ -87,7 +88,7 @@
</ul>
% else:
% if rel_link(permalink, url) == "#":
- <li class="active"><a href="${url}">${text}</a>
+ <li class="active"><a href="${permalink}">${text}</a>
%else:
<li><a href="${url}">${text}</a>
%endif
diff --git a/nikola/data/themes/bootstrap/templates/gallery.tmpl b/nikola/data/themes/bootstrap/templates/gallery.tmpl
index 17ae61c..0dd5eea 100644
--- a/nikola/data/themes/bootstrap/templates/gallery.tmpl
+++ b/nikola/data/themes/bootstrap/templates/gallery.tmpl
@@ -6,14 +6,18 @@
<%block name="content">
${ui.bar(crumbs)}
+ %if title:
+ <h1>${title}</h1>
+ %endif
%if text:
<p>
${text}
</p>
%endif
<ul>
- % for folder in folders:
- <li><a href="${folder}"><i class="icon-folder-open"></i>&nbsp;${folder}</a></li>
+ % for folder, ftitle in folders:
+ <li><a href="${folder}"><i
+ class="icon-folder-open"></i>&nbsp;${ftitle}</a></li>
% endfor
</ul>
diff --git a/nikola/filters.py b/nikola/filters.py
index 04703cb..aa7ba8a 100644
--- a/nikola/filters.py
+++ b/nikola/filters.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,6 +26,7 @@
"""Utility functions to help you run filters on files."""
+from .utils import req_missing
from functools import wraps
import os
import re
@@ -37,7 +38,7 @@ import shlex
try:
import typogrify.filters as typo
except ImportError:
- typo = None
+ typo = None # NOQA
def apply_to_file(f):
@@ -102,7 +103,21 @@ def runinplace(command, infile):
def yui_compressor(infile):
- return runinplace(r'yui-compressor --nomunge %1 -o %2', infile)
+ yuicompressor = False
+ try:
+ subprocess.call('yui-compressor', stdout=open(os.devnull, 'w'), stderr=open(os.devnull, 'w'))
+ yuicompressor = 'yui-compressor'
+ except Exception:
+ pass
+ if not yuicompressor:
+ try:
+ subprocess.call('yuicompressor', stdout=open(os.devnull, 'w'), stderr=open(os.devnull, 'w'))
+ yuicompressor = 'yuicompressor'
+ except:
+ raise Exception("yui-compressor is not installed.")
+ return False
+
+ return runinplace(r'{} --nomunge %1 -o %2'.format(yuicompressor), infile)
def optipng(infile):
@@ -114,7 +129,7 @@ def jpegoptim(infile):
def tidy(inplace):
- # Goggle site verifcation files are no HTML
+ # Google site verifcation files are not HTML
if re.match(r"google[a-f0-9]+.html", os.path.basename(inplace)) \
and open(inplace).readline().startswith(
"google-site-verification:"):
@@ -161,7 +176,8 @@ def tidy(inplace):
def typogrify(data):
global typogrify_filter
if typo is None:
- raise Exception("To use the typogrify filter, you need to install typogrify.")
+ req_missing(['typogrify', 'use the typogrify filter'])
+
data = typo.amp(data)
data = typo.widont(data)
data = typo.smartypants(data)
diff --git a/nikola/nikola.py b/nikola/nikola.py
index 13c91a7..6971c0c 100644
--- a/nikola/nikola.py
+++ b/nikola/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
@@ -43,7 +43,9 @@ except ImportError:
pyphen = None
import logging
-if os.getenv('NIKOLA_DEBUG'):
+from . import DEBUG
+
+if DEBUG:
logging.basicConfig(level=logging.DEBUG)
else:
logging.basicConfig(level=logging.ERROR)
@@ -105,6 +107,7 @@ class Nikola(object):
self._scanned = False
self._template_system = None
self._THEMES = None
+ self.debug = DEBUG
self.loghandlers = []
if not config:
self.configured = False
@@ -143,6 +146,7 @@ class Nikola(object):
'DEFAULT_LANG': "en",
'DEPLOY_COMMANDS': [],
'DISABLED_PLUGINS': (),
+ 'EXTRA_PLUGINS_DIRS': [],
'COMMENT_SYSTEM_ID': 'nikolademo',
'ENABLED_EXTRAS': (),
'EXTRA_HEAD_DATA': '',
@@ -165,8 +169,10 @@ class Nikola(object):
'INDEX_TEASERS': False,
'INDEXES_TITLE': "",
'INDEXES_PAGES': "",
+ 'INDEXES_PAGES_MAIN': False,
'INDEX_PATH': '',
'IPYNB_CONFIG': {},
+ 'LESS_COMPILER': 'lessc',
'LICENSE': '',
'LINK_CHECK_WHITELIST': [],
'LISTINGS_FOLDER': 'listings',
@@ -185,6 +191,7 @@ class Nikola(object):
'RSS_LINK': None,
'RSS_PATH': '',
'RSS_TEASERS': True,
+ 'SASS_COMPILER': 'sass',
'SEARCH_FORM': '',
'SLUG_TAG_PATH': True,
'SOCIAL_BUTTONS_CODE': SOCIAL_BUTTONS_CODE,
@@ -198,16 +205,19 @@ class Nikola(object):
'THEME_REVEAL_CONFIG_SUBTHEME': 'sky',
'THEME_REVEAL_CONFIG_TRANSITION': 'cube',
'THUMBNAIL_SIZE': 180,
+ 'URL_TYPE': 'rel_path',
'USE_BUNDLES': True,
'USE_CDN': False,
'USE_FILENAME_AS_TITLE': True,
- 'TIMEZONE': None,
+ 'TIMEZONE': 'UTC',
'DEPLOY_DRAFTS': True,
'DEPLOY_FUTURE': False,
'SCHEDULE_ALL': False,
'SCHEDULE_RULE': '',
'SCHEDULE_FORCE_TODAY': False,
'LOGGING_HANDLERS': {'stderr': {'loglevel': 'WARNING', 'bubble': True}},
+ 'DEMOTE_HEADERS': 1,
+ 'TRANSLATIONS_PATTERN': '{path}.{ext}.{lang}',
}
self.config.update(config)
@@ -337,16 +347,18 @@ class Nikola(object):
"SignalHandler": SignalHandler,
})
self.plugin_manager.setPluginInfoExtension('plugin')
+ extra_plugins_dirs = self.config['EXTRA_PLUGINS_DIRS']
if sys.version_info[0] == 3:
places = [
os.path.join(os.path.dirname(__file__), 'plugins'),
os.path.join(os.getcwd(), 'plugins'),
- ]
+ ] + [path for path in extra_plugins_dirs if path]
else:
places = [
os.path.join(os.path.dirname(__file__), utils.sys_encode('plugins')),
os.path.join(os.getcwd(), utils.sys_encode('plugins')),
- ]
+ ] + [utils.sys_encode(path) for path in extra_plugins_dirs if path]
+
self.plugin_manager.setPluginPlaces(places)
self.plugin_manager.collectPlugins()
@@ -590,6 +602,8 @@ class Nikola(object):
local_context["template_name"] = template_name
local_context.update(self.GLOBAL_CONTEXT)
local_context.update(context)
+ # string, arguments
+ local_context["formatmsg"] = lambda s, *a: s % a
data = self.template_system.render_template(
template_name, None, local_context)
@@ -617,14 +631,35 @@ class Nikola(object):
else:
return dst
+ # Refuse to replace links that consist of a fragment only
+ if ((not dst_url.scheme) and (not dst_url.netloc) and
+ (not dst_url.path) and (not dst_url.params) and
+ (not dst_url.query) and dst_url.fragment):
+ return dst
+
# Normalize
dst = urljoin(src, dst)
+
# Avoid empty links.
if src == dst:
- return "#"
+ if self.config.get('URL_TYPE') == 'absolute':
+ dst = urljoin(self.config['BASE_URL'], dst)
+ return dst
+ elif self.config.get('URL_TYPE') == 'full_path':
+ return dst
+ else:
+ return "#"
+
# Check that link can be made relative, otherwise return dest
parsed_dst = urlsplit(dst)
if parsed_src[:2] != parsed_dst[:2]:
+ if self.config.get('URL_TYPE') == 'absolute':
+ dst = urljoin(self.config['BASE_URL'], dst)
+ return dst
+
+ if self.config.get('URL_TYPE') in ('full_path', 'absolute'):
+ if self.config.get('URL_TYPE') == 'absolute':
+ dst = urljoin(self.config['BASE_URL'], dst)
return dst
# Now both paths are on the same site and absolute
@@ -733,7 +768,7 @@ class Nikola(object):
# Normalize
dst = urljoin(self.config['BASE_URL'], dst)
- return urlparse(dst).path
+ return urlparse(dst).geturl()
def rel_link(self, src, dst):
# Normalize
@@ -825,13 +860,16 @@ class Nikola(object):
full_list = glob.glob(dir_glob)
# Now let's look for things that are not in default_lang
for lang in self.config['TRANSLATIONS'].keys():
- lang_glob = dir_glob + "." + lang
+ lang_glob = utils.get_translation_candidate(self.config, dir_glob, lang)
translated_list = glob.glob(lang_glob)
- for fname in translated_list:
- orig_name = os.path.splitext(fname)[0]
- if orig_name in full_list:
- continue
- full_list.append(orig_name)
+ # dir_glob could have put it already in full_list
+ full_list = list(set(full_list + translated_list))
+ # Eliminate translations from full_list (even from dir_glob)
+ for fname in full_list:
+ translation = utils.get_translation_candidate(self.config, fname, lang)
+ if translation in full_list:
+ full_list.remove(translation)
+
# We eliminate from the list the files inside any .ipynb folder
full_list = [p for p in full_list
if not any([x.startswith('.')
@@ -849,7 +887,7 @@ class Nikola(object):
use_in_feeds,
self.MESSAGES,
template_name,
- self.get_compiler(base_path).compile_html
+ self.get_compiler(base_path)
)
self.global_data[post.source_path] = post
if post.use_in_feeds:
@@ -873,8 +911,6 @@ class Nikola(object):
self.posts_per_category[post.meta('category')].append(post.source_path)
else:
self.pages.append(post)
- if self.config['OLD_THEME_SUPPORT']:
- post._add_old_metadata()
self.post_per_file[post.destination_path(lang=lang)] = post
self.post_per_file[post.destination_path(lang=lang, extension=post.source_ext())] = post
diff --git a/nikola/plugin_categories.py b/nikola/plugin_categories.py
index 23ca287..68327aa 100644
--- a/nikola/plugin_categories.py
+++ b/nikola/plugin_categories.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
@@ -42,6 +42,12 @@ from doit.cmd_base import Command as DoitCommand
from .utils import LOGGER, first_line
+try:
+ # ordereddict does not exist in py2.6
+ from collections import OrderedDict
+except ImportError:
+ OrderedDict = None # NOQA
+
class BasePlugin(IPlugin):
"""Base plugin class."""
@@ -178,14 +184,22 @@ class PageCompiler(BasePlugin):
"""Plugins that compile text files into HTML."""
name = "dummy compiler"
- default_metadata = {
- 'title': '',
- 'slug': '',
- 'date': '',
- 'tags': '',
- 'link': '',
- 'description': '',
- }
+ demote_headers = False
+ if OrderedDict is not None:
+ default_metadata = OrderedDict()
+ else:
+ # Graceful fallback. We could use a backport, but it is
+ # not going to change anything, other than a bit uglier
+ # and nonsensical layout. Not enough to care.
+ default_metadata = {}
+
+ default_metadata['title'] = ''
+ default_metadata['slug'] = ''
+ default_metadata['date'] = ''
+ default_metadata['tags'] = ''
+ default_metadata['link'] = ''
+ default_metadata['description'] = ''
+ default_metadata['type'] = 'text'
def compile_html(self, source, dest, is_two_file=False):
"""Compile the source, save it on dest."""
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
diff --git a/nikola/post.py b/nikola/post.py
index a41901d..810474b 100644
--- a/nikola/post.py
+++ b/nikola/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
@@ -54,6 +54,8 @@ from .utils import (
slugify,
to_datetime,
unicode_str,
+ demote_headers,
+ get_translation_candidate,
)
from .rc4 import rc4
@@ -83,11 +85,11 @@ class Post(object):
the meta file, as well as any translations available, and
the .html fragment file path.
"""
- self.compiler = compiler
self.config = config
- tzinfo = None
- if self.config['TIMEZONE'] is not None:
- tzinfo = pytz.timezone(self.config['TIMEZONE'])
+ self.compiler = compiler
+ self.compile_html = self.compiler.compile_html
+ self.demote_headers = self.compiler.demote_headers and self.config['DEMOTE_HEADERS']
+ tzinfo = pytz.timezone(self.config['TIMEZONE'])
if self.config['FUTURE_IS_NOW']:
self.current_time = None
else:
@@ -127,7 +129,7 @@ class Post(object):
# Load internationalized metadata
for lang in self.translations:
if lang != self.default_lang:
- if os.path.isfile(self.source_path + "." + lang):
+ if os.path.isfile(get_translation_candidate(self.config, self.source_path, lang)):
self.translated_to.add(lang)
meta = defaultdict(lambda: '')
@@ -146,11 +148,7 @@ class Post(object):
if 'date' not in default_metadata and not use_in_feeds:
# For stories we don't *really* need a date
default_metadata['date'] = datetime.datetime.utcfromtimestamp(
- os.stat(self.source_path).st_ctime)
-
- if tzinfo:
- default_metadata['date'] = default_metadata['date'].replace(
- tzinfo=pytz.UTC).astimezone(tzinfo)
+ os.stat(self.source_path).st_ctime).replace(tzinfo=pytz.UTC).astimezone(tzinfo)
if 'title' not in default_metadata or 'slug' not in default_metadata \
or 'date' not in default_metadata:
@@ -161,7 +159,11 @@ class Post(object):
default_metadata.get('date', None),
source_path))
- # If timezone is set, build localized datetime.
+ if 'type' not in default_metadata:
+ # default value is 'text'
+ default_metadata['type'] = 'text'
+
+ # If time zone is set, build localized datetime.
self.date = to_datetime(self.meta[self.default_lang]['date'], tzinfo)
self.publish_later = False if self.current_time is None else self.date >= self.current_time
@@ -185,6 +187,7 @@ class Post(object):
# While draft comes from the tags, it's not really a tag
self.is_draft = is_draft
self.is_retired = is_retired
+ self.is_post = use_in_feeds
self.use_in_feeds = use_in_feeds and not is_draft and not is_retired \
and not self.publish_later
@@ -253,15 +256,6 @@ class Post(object):
def template_name(self):
return self.meta('template') or self._template_name
- def _add_old_metadata(self):
- # Compatibility for themes up to Nikola 5.4.1
- # TODO: remove before Nikola 6
- self.pagenames = {}
- self.titles = {}
- for lang in self.translations:
- self.pagenames[lang] = self.meta[lang]['slug']
- self.titles[lang] = self.meta[lang]['title']
-
def formatted_date(self, date_format):
"""Return the formatted date, as unicode."""
fmt_date = self.date.strftime(date_format)
@@ -292,7 +286,7 @@ class Post(object):
if self.default_lang in self.translated_to:
deps.append(self.base_path)
if lang != self.default_lang:
- deps += [self.base_path + "." + lang]
+ deps += [get_translation_candidate(self.config, self.base_path, lang)]
deps += self.fragment_deps(lang)
return deps
@@ -312,7 +306,7 @@ class Post(object):
if not self.is_translation_available(lang) and self.config['HIDE_UNTRANSLATED_POSTS']:
return
else:
- self.compiler(
+ self.compile_html(
self.translated_source_path(lang),
dest,
self.is_two_file),
@@ -333,11 +327,11 @@ class Post(object):
if os.path.isfile(dep_path):
with codecs.open(dep_path, 'rb+', 'utf8') as depf:
deps.extend([l.strip() for l in depf.readlines()])
+ lang_deps = []
if lang != self.default_lang:
- lang_deps = list(filter(os.path.exists, [x + "." + lang for x in
- deps]))
+ lang_deps = [get_translation_candidate(self.config, d, lang) for d in deps]
deps += lang_deps
- return deps
+ return [d for d in deps if os.path.exists(d)]
def is_translation_available(self, lang):
"""Return true if the translation actually exists."""
@@ -349,18 +343,18 @@ class Post(object):
if lang == self.default_lang:
return self.source_path
else:
- return '.'.join((self.source_path, lang))
+ return get_translation_candidate(self.config, self.source_path, lang)
elif lang != self.default_lang:
return self.source_path
else:
- return '.'.join((self.source_path, sorted(self.translated_to)[0]))
+ return get_translation_candidate(self.config, self.source_path, sorted(self.translated_to)[0])
def translated_base_path(self, lang):
"""Return path to the translation's base_path file."""
if lang == self.default_lang:
return self.base_path
else:
- return '.'.join((self.base_path, lang))
+ return get_translation_candidate(self.config, self.base_path, lang)
def _translated_file_path(self, lang):
"""Return path to the translation's file, or to the original."""
@@ -368,11 +362,11 @@ class Post(object):
if lang == self.default_lang:
return self.base_path
else:
- return '.'.join((self.base_path, lang))
+ return get_translation_candidate(self.config, self.base_path, lang)
elif lang != self.default_lang:
return self.base_path
else:
- return '.'.join((self.base_path, sorted(self.translated_to)[0]))
+ return get_translation_candidate(self.config, self.base_path, sorted(self.translated_to)[0])
def text(self, lang=None, teaser_only=False, strip_html=False, really_absolute=False):
"""Read the post file for that language and return its contents.
@@ -438,6 +432,16 @@ class Post(object):
data = content.text_content().strip() # No whitespace wanted.
except lxml.etree.ParserError:
data = ""
+ elif data:
+ if self.demote_headers:
+ # see above
+ try:
+ document = lxml.html.fromstring(data)
+ demote_headers(document, self.demote_headers)
+ data = lxml.html.tostring(document, encoding='unicode')
+ except lxml.etree.ParserError:
+ pass
+
return data
@property
@@ -536,11 +540,13 @@ def _get_metadata_from_filename_by_regex(filename, metadata_regexp):
return meta
-def get_metadata_from_file(source_path, lang=None):
+def get_metadata_from_file(source_path, config=None, lang=None):
"""Extracts metadata from the file itself, by parsing contents."""
try:
- if lang:
- source_path = "{0}.{1}".format(source_path, lang)
+ if lang and config:
+ source_path = get_translation_candidate(config, source_path, lang)
+ elif lang:
+ source_path += '.' + lang
with codecs.open(source_path, "r", "utf8") as meta_file:
meta_data = [x.strip() for x in meta_file.readlines()]
return _get_metadata_from_file(meta_data)
@@ -601,18 +607,20 @@ def _get_metadata_from_file(meta_data):
return meta
-def get_metadata_from_meta_file(path, lang=None):
+def get_metadata_from_meta_file(path, config=None, lang=None):
"""Takes a post path, and gets data from a matching .meta file."""
meta_path = os.path.splitext(path)[0] + '.meta'
- if lang:
+ if lang and config:
+ meta_path = get_translation_candidate(config, meta_path, lang)
+ elif lang:
meta_path += '.' + lang
if os.path.isfile(meta_path):
with codecs.open(meta_path, "r", "utf8") as meta_file:
meta_data = meta_file.readlines()
- while len(meta_data) < 6:
+ while len(meta_data) < 7:
meta_data.append("")
- (title, slug, date, tags, link, description) = [
- x.strip() for x in meta_data][:6]
+ (title, slug, date, tags, link, description, _type) = [
+ x.strip() for x in meta_data][:7]
meta = {}
@@ -628,6 +636,8 @@ def get_metadata_from_meta_file(path, lang=None):
meta['link'] = link
if description:
meta['description'] = description
+ if _type:
+ meta['type'] = _type
return meta
@@ -635,7 +645,7 @@ def get_metadata_from_meta_file(path, lang=None):
# Metadata file doesn't exist, but not default language,
# So, if default language metadata exists, return that.
# This makes the 2-file format detection more reliable (Issue #525)
- return get_metadata_from_meta_file(path, lang=None)
+ return get_metadata_from_meta_file(path, config, lang=None)
else:
return {}
@@ -650,7 +660,12 @@ def get_meta(post, file_metadata_regexp=None, lang=None):
"""
meta = defaultdict(lambda: '')
- meta.update(get_metadata_from_meta_file(post.metadata_path, lang))
+ try:
+ config = post.config
+ except AttributeError:
+ config = None
+
+ meta.update(get_metadata_from_meta_file(post.metadata_path, config, lang))
if meta:
return meta
@@ -660,7 +675,7 @@ def get_meta(post, file_metadata_regexp=None, lang=None):
meta.update(_get_metadata_from_filename_by_regex(post.source_path,
file_metadata_regexp))
- meta.update(get_metadata_from_file(post.source_path, lang))
+ meta.update(get_metadata_from_file(post.source_path, config, lang))
if lang is None:
# Only perform these checks for the default language
diff --git a/nikola/rc4.py b/nikola/rc4.py
index fe2ab17..b46d602 100644
--- a/nikola/rc4.py
+++ b/nikola/rc4.py
@@ -1,5 +1,7 @@
# -*- coding: utf-8 -*-
"""
+ A RC4 encryption library (used for password-protected posts)
+ ---
Copyright (C) 2012 Bo Zhu http://about.bozhu.me
Permission is hereby granted, free of charge, to any person obtaining a
diff --git a/nikola/utils.py b/nikola/utils.py
index 0a615f8..0c3b4c0 100644
--- a/nikola/utils.py
+++ b/nikola/utils.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,8 @@ import logbook
from logbook.more import ExceptionHandler
import pytz
+from . import DEBUG
+
class ApplicationWarning(Exception):
pass
@@ -67,13 +69,13 @@ def get_logger(name, handlers):
STDERR_HANDLER = [logbook.StderrHandler(
- level=logbook.NOTICE if not os.getenv('NIKOLA_DEBUG') else logbook.DEBUG,
+ level=logbook.NOTICE if not DEBUG else logbook.DEBUG,
format_string=u'[{record.time:%Y-%m-%dT%H:%M:%SZ}] {record.level_name}: {record.channel}: {record.message}'
)]
LOGGER = get_logger('Nikola', STDERR_HANDLER)
STRICT_HANDLER = ExceptionHandler(ApplicationWarning, level='WARNING')
-if os.getenv('NIKOLA_DEBUG'):
+if DEBUG:
logging.basicConfig(level=logging.DEBUG)
else:
logging.basicConfig(level=logging.WARNING)
@@ -101,7 +103,8 @@ def req_missing(names, purpose, python=True, optional=False):
LOGGER.warn(msg)
else:
LOGGER.error(msg)
- raise Exception('Missing dependencies: {0}'.format(', '.join(names)))
+ LOGGER.error('Exiting due to missing dependencies.')
+ sys.exit(5)
return msg
@@ -127,7 +130,8 @@ __all__ = ['get_theme_path', 'get_theme_chain', 'load_messages', 'copy_tree',
'to_datetime', 'apply_filters', 'config_changed', 'get_crumbs',
'get_tzname', 'get_asset_path', '_reload', 'unicode_str', 'bytes_str',
'unichr', 'Functionary', 'LocaleBorg', 'sys_encode', 'sys_decode',
- 'makedirs', 'get_parent_theme_name', 'ExtendedRSS2']
+ 'makedirs', 'get_parent_theme_name', 'ExtendedRSS2', 'demote_headers',
+ 'get_translation_candidate']
ENCODING = sys.getfilesystemencoding() or sys.stdin.encoding
@@ -346,7 +350,7 @@ def generic_rss_renderer(lang, title, link, description, timeline, output_path,
description=description,
lastBuildDate=datetime.datetime.now(),
items=items,
- generator='nikola',
+ generator='Nikola <http://getnikola.com/>',
language=lang
)
rss_obj.self_url = feed_url
@@ -477,7 +481,7 @@ def to_datetime(value, tzinfo=None):
dt = datetime.datetime.strptime(value, format)
if tzinfo is None:
return dt
- # Build a localized time by using a given timezone.
+ # Build a localized time by using a given time zone.
return tzinfo.localize(dt)
except ValueError:
pass
@@ -496,7 +500,7 @@ def to_datetime(value, tzinfo=None):
def get_tzname(dt):
"""
- Give a datetime value, find the name of the timezone
+ Given a datetime value, find the name of the time zone.
"""
try:
from dateutil import tz
@@ -555,8 +559,10 @@ def apply_filters(task, filters):
return task
-def get_crumbs(path, is_file=False):
+def get_crumbs(path, is_file=False, index_folder=None):
"""Create proper links for a crumb bar.
+ index_folder is used if you want to use title from index file
+ instead of folder name as breadcrumb text.
>>> crumbs = get_crumbs('galleries')
>>> len(crumbs)
@@ -595,6 +601,16 @@ def get_crumbs(path, is_file=False):
for i, crumb in enumerate(crumbs[::-1]):
_path = '/'.join(['..'] * i) or '#'
_crumbs.append([_path, crumb])
+ if index_folder and hasattr(index_folder, 'parse_index'):
+ folder = path
+ for i, crumb in enumerate(crumbs[::-1]):
+ if folder[-1] == os.sep:
+ folder = folder[:-1]
+ index_post = index_folder.parse_index(folder)
+ folder = folder.replace(crumb, '')
+ if index_post:
+ crumb = index_post.title() or crumb
+ _crumbs[i][1] = crumb
return list(reversed(_crumbs))
@@ -792,3 +808,46 @@ def first_line(doc):
if striped:
return striped
return ''
+
+
+def demote_headers(doc, level=1):
+ """Demote <hN> elements by one."""
+ if level == 0:
+ return doc
+ elif level > 0:
+ r = range(1, 7 - level)
+ elif level < 0:
+ r = range(1 + level, 7)
+ for i in reversed(r):
+ # html headers go to 6, so we can’t “lower” beneath five
+ elements = doc.xpath('//h' + str(i))
+ for e in elements:
+ e.tag = 'h' + str(i + level)
+
+
+def get_root_dir():
+ """Find root directory of nikola installation by looking for conf.py"""
+ root = os.getcwd()
+
+ while True:
+ if os.path.exists(os.path.join(root, 'conf.py')):
+ return root
+ else:
+ basedir = os.path.split(root)[0]
+ # Top directory, already checked
+ if basedir == root:
+ break
+ root = basedir
+
+ return None
+
+
+def get_translation_candidate(config, path, lang):
+ """
+ Return a possible path where we can find the translated version of some page
+ based on the TRANSLATIONS_PATTERN configuration variable
+ """
+ pattern = config['TRANSLATIONS_PATTERN']
+ path, ext = os.path.splitext(path)
+ ext = ext[1:] if len(ext) > 0 else ext
+ return pattern.format(path=path, lang=lang, ext=ext)
diff --git a/nikola/winutils.py b/nikola/winutils.py
index 291c99d..517a326 100644
--- a/nikola/winutils.py
+++ b/nikola/winutils.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