Skip to content
Permalink
Browse files

merged trunk

  • Loading branch information...
ralsina committed May 2, 2015
2 parents a7a03d5 + 0b93441 commit 6c23948b737a6bc7f29b871005f0bbcb265c107d
@@ -5,6 +5,8 @@ Features
--------

* Multilingual sitemaps (Issue #1610)
* Compatibility with doit v0.28.0 (Issue #1655)
* AddThis is no longer added by default to users’ sites
* New translations (az, fil, tl, uk, zh_TW)
* Add reStructuredText transform support (Issue #1647)
* Produce Unicode output in ``nikola init`` (via Issue #1644)
@@ -17,6 +19,8 @@ Features
Bugfixes
--------

* Encode IDNs to Punycode in ``nikola init`` and in links;
show an error if the site URL is not Punycode (Issue #1644)
* Make ``images`` the default output directory for IMAGE_FOLDERS
(Issue #1663)
* Don't default to any swatch in bootswatch_theme (Issue #1656)
@@ -1182,7 +1182,8 @@ to one of "disqus", "intensedebate", "livefyre", "moot", "googleplus",
* For Facebook, you need to `create an app
<https://developers.facebook.com/apps>` (turn off sandbox mode!)
and get an **App ID**
* For isso, it is the URL of isso (must be world-accessible and **have a trailing slash**,
* For isso, it is the URL of isso (must be world-accessible, encoded with
Punycode (if using Internationalized Domain Names) and **have a trailing slash**,
default ``http://localhost:8080/``)

To use comments in a visible site, you should register with the service and
@@ -25,7 +25,6 @@
# SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

from __future__ import print_function, unicode_literals
from operator import attrgetter
import os
import shutil
try:
@@ -75,7 +74,7 @@ def main(args=None):
conf_filename = 'conf.py'
conf_filename_changed = False
for index, arg in enumerate(args):
if arg[:7] == '--conf=':
if arg[:7] == b'--conf=':
del args[index]
conf_filename = arg[7:]
conf_filename_changed = True
@@ -172,8 +171,9 @@ def print_usage(cmds):

print("Nikola is a tool to create static websites and blogs. For full documentation and more information, please visit http://getnikola.com/\n\n")
print("Available commands:")
for cmd in sorted(cmds.values(), key=attrgetter('name')):
print(" nikola %-*s %s" % (20, cmd.name, cmd.doc_purpose))
for cmd_name in sorted(cmds.keys()):
cmd = cmds[cmd_name]
print(" nikola {:20s} {}".format(cmd_name, cmd.doc_purpose))
print("")
print(" nikola help show help / reference")
print(" nikola help <command> show command usage")
@@ -265,20 +265,21 @@ class DoitNikola(DoitMain):
TASK_LOADER = NikolaTaskLoader

def __init__(self, nikola, quiet=False):
super(DoitNikola, self).__init__()
self.nikola = nikola
nikola.doit = self
self.task_loader = self.TASK_LOADER(nikola, quiet)

def get_commands(self):
def get_cmds(self):
# core doit commands
cmds = DoitMain.get_commands(self)
cmds = DoitMain.get_cmds(self)
# load nikola commands
for name, cmd in self.nikola._commands.items():
cmds[name] = cmd
return cmds

def run(self, cmd_args):
sub_cmds = self.get_commands()
sub_cmds = self.get_cmds()
args = self.process_args(cmd_args)
args = [sys_decode(arg) for arg in args]

@@ -306,7 +307,7 @@ def run(self, cmd_args):
if args[0] not in sub_cmds.keys():
LOGGER.error("Unknown command {0}".format(args[0]))
return 3
if not isinstance(sub_cmds[args[0]], (Command, Help)): # Is a doit command
if sub_cmds[args[0]] is not Help and not isinstance(sub_cmds[args[0]], Command): # Is a doit command
if not self.nikola.configured:
LOGGER.error("This command needs to run inside an "
"existing Nikola site.")
@@ -492,28 +492,28 @@ IMAGE_FOLDERS = {'images': 'images'}
# algol
# algol_nu
# arduino
# autumn
# borland
# bw
# colorful
# default
# emacs
# friendly
# fruity
# autumn
# borland
# bw
# colorful
# default
# emacs
# friendly
# fruity
# igor
# lovelace
# manni
# monokai
# murphy
# native
# monokai
# murphy
# native
# paraiso_dark
# paraiso_light
# pastie
# perldoc
# rrt
# tango
# trac
# vim
# pastie
# perldoc
# rrt
# tango
# trac
# vim
# vs
# xcode
# This list MAY be incomplete since pygments adds styles every now and then.
@@ -721,7 +721,8 @@ COMMENT_SYSTEM_ID = ${COMMENT_SYSTEM_ID}
# PANDOC_OPTIONS = []

# Social buttons. This is sample code for AddThis (which was the default for a
# long time). Insert anything you want here, or even make it empty.
# long time). Insert anything you want here, or even make it empty (which is
# the default right now)
# (translatable)
# SOCIAL_BUTTONS_CODE = """
# <!-- Social buttons -->
@@ -37,9 +37,9 @@
import sys
import mimetypes
try:
from urlparse import urlparse, urlsplit, urljoin
from urlparse import urlparse, urlsplit, urlunsplit, urljoin, unquote
except ImportError:
from urllib.parse import urlparse, urlsplit, urljoin # NOQA
from urllib.parse import urlparse, urlsplit, urlunsplit, urljoin, unquote # NOQA

try:
import pyphen
@@ -407,7 +407,7 @@ def __init__(self, **config):
'SHOW_SOURCELINK': True,
'SHOW_UNTRANSLATED_POSTS': True,
'SLUG_TAG_PATH': True,
'SOCIAL_BUTTONS_CODE': SOCIAL_BUTTONS_CODE,
'SOCIAL_BUTTONS_CODE': '',
'SITE_URL': 'http://getnikola.com/',
'STORY_INDEX': False,
'STRIP_INDEXES': False,
@@ -625,6 +625,15 @@ def __init__(self, **config):
utils.LOGGER.warn("Your BASE_URL doesn't end in / -- adding it, but please fix it in your config file!")
self.config['BASE_URL'] += '/'

try:
_bnl = urlsplit(self.config['BASE_URL']).netloc
_bnl.encode('ascii')
urlsplit(self.config['SITE_URL']).netloc.encode('ascii')
except (UnicodeEncodeError, UnicodeDecodeError):
utils.LOGGER.error("Your BASE_URL or SITE_URL contains an IDN expressed in Unicode. Please convert it to Punycode.")
utils.LOGGER.error("Punycode of {}: {}".format(_bnl, _bnl.encode('idna')))
sys.exit(1)

# todo: remove in v8
if not isinstance(self.config['DEPLOY_COMMANDS'], dict):
utils.LOGGER.warn("A single list as DEPLOY_COMMANDS is deprecated. DEPLOY_COMMANDS should be a dict, with deploy preset names as keys and lists of commands as values.")
@@ -984,6 +993,24 @@ def url_replacer(self, src, dst, lang=None, url_type=None):
if dst_url.scheme == 'link': # Magic link
dst = self.link(dst_url.netloc, dst_url.path.lstrip('/'), lang)
else:
print(dst)
if '%' in dst_url.netloc:
# convert lxml percent-encoded garbage to punycode
nl = unquote(dst_url.netloc)
try:
nl = nl.decode('utf-8')
except AttributeError:
# python 3: already unicode
pass

nl = nl.encode('idna')

dst = urlunsplit((dst_url.scheme,
nl,
dst_url.path,
dst_url.query,
dst_url.fragment))
print(dst)
return dst
elif dst_url.scheme == 'link': # Magic absolute path link:
dst = dst_url.path
@@ -1315,10 +1342,6 @@ def scan_posts(self, really=False, ignore_quit=False, quiet=False):
if self._scanned and not really:
return

try:
self.commands = utils.Commands(self.doit)
except AttributeError:
self.commands = None
self.global_data = {}
self.posts = []
self.all_posts = []
@@ -1829,18 +1852,3 @@ def workaround_empty_LC_ALL_posix():
"tr_tr": "Turkish",
"zh_cn": "Chinese_China", # Chinese (Simplified)
}


SOCIAL_BUTTONS_CODE = """
<!-- Social buttons -->
<div id="addthisbox" class="addthis_toolbox addthis_peekaboo_style addthis_default_style addthis_label_style addthis_32x32_style">
<a class="addthis_button_more">Share</a>
<ul><li><a class="addthis_button_facebook"></a>
<li><a class="addthis_button_google_plusone_share"></a>
<li><a class="addthis_button_linkedin"></a>
<li><a class="addthis_button_twitter"></a>
</ul>
</div>
<script src="//s7.addthis.com/js/300/addthis_widget.js#pubid=ra-4f7088a56bb93798"></script>
<!-- End of social buttons -->
"""
@@ -93,6 +93,11 @@ def __init__(self, *args, **kwargs):
BasePlugin.__init__(self, *args, **kwargs)
DoitCommand.__init__(self)

def __call__(self, config=None, **kwargs):
self._doitargs = kwargs
DoitCommand.__init__(self, config, **kwargs)
return self

def execute(self, options=None, args=None):
"""Check if the command can run in the current environment,
fail if needed, or call _execute."""
@@ -120,7 +125,7 @@ def help(self):
text.append('')

text.append("Options:")
for opt in self.options:
for opt in self.cmdparser.options:
text.extend(opt.help_doc())

if self.doc_description is not None:
@@ -40,9 +40,7 @@
from nikola.utils import get_logger


def _call_nikola_list(site, arguments):
l = site.doit.sub_cmds['list']

def _call_nikola_list(l, site, arguments):
class NotReallyAStream(object):
"""A massive hack."""
out = []
@@ -60,12 +58,12 @@ def write(self, t):
l.outstream = oldstream


def real_scan_files(site):
def real_scan_files(l, 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 _call_nikola_list(site, ["--all"]):
for task in _call_nikola_list(l, site, ["--all"]):
task = task.strip()
if output_folder in task and ':' in task:
fname = task.split(':', 1)[-1]
@@ -143,8 +141,8 @@ class CommandCheck(Command):

def _execute(self, options, args):
"""Check the generated site."""

self.logger = get_logger('check', self.site.loghandlers)
self.l = self._doitargs['cmds'].get_plugin('list')(config=self.config, **self._doitargs)

if not options['links'] and not options['files'] and not options['clean']:
print(self.help())
@@ -230,7 +228,7 @@ def analyze(self, task, find_sources=False):
self.logger.warn("Broken link in {0}: {1}".format(filename, target))
if find_sources:
self.logger.warn("Possible sources:")
self.logger.warn("\n".join(_call_nikola_list(self.site, ["--deps", task])))
self.logger.warn("\n".join(_call_nikola_list(self.l, self.site, ["--deps", task])))
self.logger.warn("===============================\n")
except Exception as exc:
self.logger.error("Error with: {0} {1}".format(filename, exc))
@@ -241,7 +239,7 @@ def scan_links(self, find_sources=False):
self.logger.info("===============\n")
self.logger.notice("{0} mode".format(self.site.config['URL_TYPE']))
failure = False
for task in _call_nikola_list(self.site, ["--all"]):
for task in _call_nikola_list(self.l, self.site, ["--all"]):
task = task.strip()
if task.split(':')[0] in (
'render_tags', 'render_archive',
@@ -258,7 +256,7 @@ def scan_files(self):
failure = False
self.logger.info("Checking Files:")
self.logger.info("===============\n")
only_on_output, only_on_input = real_scan_files(self.site)
only_on_output, only_on_input = real_scan_files(self.l, self.site)

# Ignore folders
only_on_output = [p for p in only_on_output if not os.path.isdir(p)]
@@ -280,7 +278,7 @@ def scan_files(self):
return failure

def clean_files(self):
only_on_output, _ = real_scan_files(self.site)
only_on_output, _ = real_scan_files(self.l, self.site)
for f in only_on_output:
os.unlink(f)
return True
@@ -30,7 +30,7 @@

from nikola import __version__
from nikola.plugin_categories import Command
from nikola.utils import get_logger, STDERR_HANDLER, req_missing
from nikola.utils import get_logger, STDERR_HANDLER, req_missing, Commands

LOGGER = get_logger('console', STDERR_HANDLER)

@@ -122,6 +122,8 @@ def _execute(self, options, args):
self.site.scan_posts()
# Create nice object with all commands:

self.site.commands = Commands(self.site.doit, self.config, self._doitargs)

self.context = {
'conf': self.site.config,
'site': self.site,
Oops, something went wrong.

0 comments on commit 6c23948

Please sign in to comment.
You can’t perform that action at this time.