Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: getnikola/nikola
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: d1bc076f6158
Choose a base ref
...
head repository: getnikola/nikola
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: dd49ef6e26ff
Choose a head ref

Commits on Sep 4, 2015

  1. Copy the full SHA
    9d1a505 View commit details
  2. merged master

    ralsina committed Sep 4, 2015
    Copy the full SHA
    dbb0403 View commit details
  3. another one

    ralsina committed Sep 4, 2015
    Copy the full SHA
    254f4e3 View commit details
  4. fixie fixie

    ralsina committed Sep 4, 2015
    Copy the full SHA
    e90a68f View commit details
  5. Copy the full SHA
    d2f5590 View commit details

Commits on Sep 5, 2015

  1. Check REDIRECTIONS. Fixes #2026.

    da2x committed Sep 5, 2015
    Copy the full SHA
    41a9a82 View commit details
  2. flake8

    da2x committed Sep 5, 2015
    Copy the full SHA
    5964e52 View commit details
  3. Update conf.py.in

    Kwpolska committed Sep 5, 2015
    Copy the full SHA
    4a2039a View commit details
  4. Merge pull request #2024 from getnikola/translatable-PATHS

    Make TAG_PATH and CATEGORY_PATH translatable (part of #1914)
    Kwpolska committed Sep 5, 2015
    Copy the full SHA
    f3f855f View commit details
  5. Copy the full SHA
    5d2b740 View commit details
  6. Copy the full SHA
    f8798e5 View commit details

Commits on Sep 6, 2015

  1. Merge pull request #2027 from getnikola/optimize-nikola-check

    Optimize nikola check
    Kwpolska committed Sep 6, 2015
    Copy the full SHA
    27dca29 View commit details
  2. Copy the full SHA
    d8992df View commit details
  3. Copy the full SHA
    e3d1f1d View commit details
  4. 2
    Copy the full SHA
    d53f162 View commit details
  5. flake8

    da2x committed Sep 6, 2015
    Copy the full SHA
    b77baaa View commit details
  6. Copy the full SHA
    bcbffc4 View commit details
  7. Fixed fatal typo.

    felixfontein committed Sep 6, 2015
    Copy the full SHA
    7b3609e View commit details
  8. Merge pull request #2031 from getnikola/fix-untranslated-post-build

    Avoiding Nikola trying to cache posts which aren't written anyway.
    Kwpolska committed Sep 6, 2015
    Copy the full SHA
    e971b1c View commit details
  9. Copy the full SHA
    1823d2f View commit details
  10. Merge pull request #2028 from getnikola/fix-atom-renderer

    Fixing atom feed renderer for empty post lists.
    Kwpolska committed Sep 6, 2015
    Copy the full SHA
    f68bf4f View commit details
  11. Copy the full SHA
    aa6d0cc View commit details
  12. Merge pull request #2033 from getnikola/localize-date-format

    Making DATE_FORMAT translatable.
    Kwpolska committed Sep 6, 2015
    Copy the full SHA
    621f2ee View commit details

Commits on Sep 7, 2015

  1. fix

    ralsina committed Sep 7, 2015
    Copy the full SHA
    ad24c22 View commit details
  2. merged master

    ralsina committed Sep 7, 2015
    Copy the full SHA
    dd49ef6 View commit details
Showing with 98 additions and 49 deletions.
  1. +7 −2 CHANGES.txt
  2. +4 −2 nikola/conf.py.in
  3. +3 −0 nikola/data/themes/bootstrap3/templates/base_helper.tmpl
  4. +21 −5 nikola/nikola.py
  5. +27 −12 nikola/plugins/command/check.py
  6. +2 −0 nikola/plugins/task/posts.py
  7. +10 −10 nikola/plugins/task/tags.py
  8. +8 −17 nikola/post.py
  9. +16 −1 nikola/utils.py
9 changes: 7 additions & 2 deletions CHANGES.txt
Original file line number Diff line number Diff line change
@@ -5,12 +5,17 @@ Features
--------

* Allow inheriting templates with theme name (Issue #1814)
* Made TAG_PATH translatable (Issue #1914)
* Made CATEGORY_PATH translatable (Issue #1914)
* Display post counts for archive links (Issue #2011)
* Document link/path handlers (Issue #2008)
* Made DATE_FORMAT and JS_DATE_FORMAT translatable (Issue #2032)

Bugfixes
--------

* Multi-lingual and multi-level directories confused section slug
detection (Issue #2023)
* Use Unicode strings for WordPress comment headers (Issue #2019)
* Don't add stories to author pages (Issue #2007)

@@ -48,8 +53,8 @@ Bugfixes
* Make nikola tabcompletion work outside sites (Issue #1983)
* Fix display of categories list in bootstrap theme (Issue #2002)
* If webassets is not installed, use unbundled assets (Issue #1992)
* Check links in Atom and sitemap files (Issue #1993)
* Link checker should check all absolute URLs to self (Issue #1991)
* Check links in Atom and sitemap files (Issue #1993)
* Link checker should check all absolute URLs to self (Issue #1991)
* Check ``img|source[@srcset]`` as part of ``check -l`` (Issue #1989)
* Clean up translations for third party components
* ``pagekind["main_index"]`` set on the main indexes to differentiate
6 changes: 4 additions & 2 deletions nikola/conf.py.in
Original file line number Diff line number Diff line change
@@ -140,11 +140,11 @@ TIMEZONE = ${TIMEZONE}
# Note that this does not affect DATE_FORMAT.
# FORCE_ISO8601 = False

# Date format used to display post dates.
# Date format used to display post dates. (translatable)
# (str used by datetime.datetime.strftime)
# DATE_FORMAT = '%Y-%m-%d %H:%M'

# Date format used to display post dates, if local dates are used.
# Date format used to display post dates, if local dates are used. (translatable)
# (str used by moment.js)
# JS_DATE_FORMAT = 'YYYY-MM-DD HH:mm'

@@ -271,6 +271,7 @@ POSTS_SECTIONS = True
# output / TRANSLATION[lang] / TAG_PATH / index.html (list of tags)
# output / TRANSLATION[lang] / TAG_PATH / tag.html (list of posts for a tag)
# output / TRANSLATION[lang] / TAG_PATH / tag.xml (RSS feed for a tag)
# (translatable)
# TAG_PATH = "categories"

# If TAG_PAGES_ARE_INDEXES is set to True, each tag's page will contain
@@ -310,6 +311,7 @@ HIDDEN_TAGS = ['mathjax']
# output / TRANSLATION[lang] / CATEGORY_PATH / index.html (list of categories)
# output / TRANSLATION[lang] / CATEGORY_PATH / CATEGORY_PREFIX category.html (list of posts for a category)
# output / TRANSLATION[lang] / CATEGORY_PATH / CATEGORY_PREFIX category.xml (RSS feed for a category)
# (translatable)
# CATEGORY_PATH = "categories"
# CATEGORY_PREFIX = "cat_"

3 changes: 3 additions & 0 deletions nikola/data/themes/bootstrap3/templates/base_helper.tmpl
Original file line number Diff line number Diff line change
@@ -155,6 +155,9 @@ lang="${lang}">
%endfor
</%def>

<%def name="html_translations()">
${parent.html_translations()}
</%def>

<%def name="html_feedlinks()">
${parent.html_feedlinks()}
26 changes: 21 additions & 5 deletions nikola/nikola.py
Original file line number Diff line number Diff line change
@@ -549,7 +549,13 @@ def __init__(self, **config):
'POSTS_SECTION_NAME',
'POSTS_SECTION_TITLE',
'INDEXES_PAGES',
'INDEXES_PRETTY_PAGE_URL',)
'INDEXES_PRETTY_PAGE_URL',
# PATH options (Issue #1914)
'TAG_PATH',
'CATEGORY_PATH',
'DATE_FORMAT',
'JS_DATE_FORMAT',
)

self._GLOBAL_CONTEXT_TRANSLATABLE = ('blog_author',
'blog_title',
@@ -560,10 +566,20 @@ def __init__(self, **config):
'social_buttons_code',
'search_form',
'body_end',
'extra_head_data',)
'extra_head_data',
'date_format',
'js_date_format',)
# WARNING: navigation_links SHOULD NOT be added to the list above.
# Themes ask for [lang] there and we should provide it.

# We first have to massage JS_DATE_FORMAT, otherwise we run into trouble
if 'JS_DATE_FORMAT' in self.config:
if isinstance(self.config['JS_DATE_FORMAT'], dict):
for k in self.config['JS_DATE_FORMAT']:
self.config['JS_DATE_FORMAT'][k] = json.dumps(self.config['JS_DATE_FORMAT'][k])
else:
self.config['JS_DATE_FORMAT'] = json.dumps(self.config['JS_DATE_FORMAT'])

for i in self.TRANSLATABLE_SETTINGS:
try:
self.config[i] = utils.TranslatableSetting(i, self.config[i], self.config['TRANSLATIONS'])
@@ -670,7 +686,7 @@ def __init__(self, **config):
if not self.config.get('COPY_SOURCES'):
self.config['SHOW_SOURCELINK'] = False

if self.config['CATEGORY_PATH'] is None:
if self.config['CATEGORY_PATH']._inp is None:
self.config['CATEGORY_PATH'] = self.config['TAG_PATH']
if self.config['CATEGORY_PAGES_ARE_INDEXES'] is None:
self.config['CATEGORY_PAGES_ARE_INDEXES'] = self.config['TAG_PAGES_ARE_INDEXES']
@@ -920,7 +936,7 @@ def _set_global_context(self):
'SHOW_SOURCELINK')
self._GLOBAL_CONTEXT['extra_head_data'] = self.config.get('EXTRA_HEAD_DATA')
self._GLOBAL_CONTEXT['date_fanciness'] = self.config.get('DATE_FANCINESS')
self._GLOBAL_CONTEXT['js_date_format'] = json.dumps(self.config.get('JS_DATE_FORMAT'))
self._GLOBAL_CONTEXT['js_date_format'] = self.config.get('JS_DATE_FORMAT')
self._GLOBAL_CONTEXT['colorbox_locales'] = LEGAL_VALUES['COLORBOX_LOCALES']
self._GLOBAL_CONTEXT['momentjs_locales'] = LEGAL_VALUES['MOMENTJS_LOCALES']
self._GLOBAL_CONTEXT['hidden_tags'] = self.config.get('HIDDEN_TAGS')
@@ -1820,7 +1836,7 @@ def atom_link(link_rel, link_type, link_href):
feed_id = lxml.etree.SubElement(feed_root, "id")
feed_id.text = self.abs_link(context["feedlink"])
feed_updated = lxml.etree.SubElement(feed_root, "updated")
feed_updated.text = post.formatted_date('webiso', datetime.datetime.now(tz=dateutil.tz.tzutc()))
feed_updated.text = utils.formatted_date('webiso', datetime.datetime.now(tz=dateutil.tz.tzutc()))
feed_author = lxml.etree.SubElement(feed_root, "author")
feed_author_name = lxml.etree.SubElement(feed_author, "name")
feed_author_name.text = self.config["BLOG_AUTHOR"](lang)
39 changes: 27 additions & 12 deletions nikola/plugins/command/check.py
Original file line number Diff line number Diff line change
@@ -46,7 +46,10 @@
from nikola.utils import get_logger, STDERR_HANDLER


def _call_nikola_list(site):
def _call_nikola_list(site, cache=None):
if cache is not None:
if 'files' in cache and 'deps' in cache:
return cache['files'], cache['deps']
files = []
deps = defaultdict(list)
for task in generate_tasks('render_site', site.gen_tasks('render_site', "Task", '')):
@@ -57,16 +60,19 @@ def _call_nikola_list(site):
files.extend(task.targets)
for target in task.targets:
deps[target].extend(task.file_dep)
if cache is not None:
cache['files'] = files
cache['deps'] = deps
return files, deps


def real_scan_files(site):
def real_scan_files(site, cache=None):
"""Scan for files."""
task_fnames = set([])
real_fnames = set([])
output_folder = site.config['OUTPUT_FOLDER']
# First check that all targets are generated in the right places
for fname in _call_nikola_list(site)[0]:
for fname in _call_nikola_list(site, cache)[0]:
fname = fname.strip()
if fname.startswith(output_folder):
task_fnames.add(fname)
@@ -162,30 +168,33 @@ def _execute(self, options, args):
self.logger.level = 1
else:
self.logger.level = 4
failure = False
if options['links']:
failure = self.scan_links(options['find_sources'], options['remote'])
failure |= self.scan_links(options['find_sources'], options['remote'])
if options['files']:
failure = self.scan_files()
failure |= self.scan_files()
if options['clean']:
failure = self.clean_files()
failure |= self.clean_files()
if failure:
return 1

existing_targets = set([])
checked_remote_targets = {}
cache = {}

def analyze(self, fname, find_sources=False, check_remote=False):
"""Analyze links on a page."""
rv = False
self.whitelist = [re.compile(x) for x in self.site.config['LINK_CHECK_WHITELIST']]
self.internal_redirects = [urljoin('/', _[0]) for _ in self.site.config['REDIRECTIONS']]
base_url = urlparse(self.site.config['BASE_URL'])
self.existing_targets.add(self.site.config['SITE_URL'])
self.existing_targets.add(self.site.config['BASE_URL'])
url_type = self.site.config['URL_TYPE']

deps = {}
if find_sources:
deps = _call_nikola_list(self.site)[1]
deps = _call_nikola_list(self.site, self.cache)[1]

if url_type in ('absolute', 'full_path'):
url_netloc_to_root = urlparse(self.site.config['BASE_URL']).path
@@ -250,16 +259,22 @@ def analyze(self, fname, find_sources=False, check_remote=False):
if base_url.netloc == parsed.netloc and base_url.scheme == "https" and parsed.scheme == "http":
self.logger.warn("Mixed-content security for link in {0}: {1}".format(filename, target))

# Link to an internal REDIRECTIONS page
if target in self.internal_redirects:
redir_status_code = 301
redir_target = [_dest for _target, _dest in self.site.config['REDIRECTIONS'] if urljoin('/', _target) == target][0]
self.logger.warn("Remote link moved PERMANENTLY to \"{0}\" and should be updated in {1}: {2} [HTTP: 301]".format(redir_target, filename, target))

# Absolute links to other domains, skip
# Absolute links when using only paths, skip.
if ((parsed.scheme or target.startswith('//')) and parsed.netloc != base_url.netloc) or \
((parsed.scheme or target.startswith('//')) and url_type in ('rel_path', 'full_path')):
if not check_remote or parsed.scheme not in ["http", "https"]:
continue
if target in self.checked_remote_targets: # already checked this exact target
if self.checked_remote_targets[target] in [301, 307]:
if self.checked_remote_targets[target] in [301, 308]:
self.logger.warn("Remote link PERMANENTLY redirected in {0}: {1} [Error {2}]".format(filename, target, self.checked_remote_targets[target]))
elif self.checked_remote_targets[target] in [302, 308]:
elif self.checked_remote_targets[target] in [302, 307]:
self.logger.info("Remote link temporarily redirected in {1}: {2} [HTTP: {3}]".format(filename, target, self.checked_remote_targets[target]))
elif self.checked_remote_targets[target] > 399:
self.logger.error("Broken link in {0}: {1} [Error {2}]".format(filename, target, self.checked_remote_targets[target]))
@@ -352,7 +367,7 @@ def scan_links(self, find_sources=False, check_remote=False):
if urlparse(self.site.config['BASE_URL']).netloc == 'example.com':
self.logger.error("You've not changed the SITE_URL (or BASE_URL) setting from \"example.com\"!")

for fname in _call_nikola_list(self.site)[0]:
for fname in _call_nikola_list(self.site, self.cache)[0]:
if fname.startswith(output_folder):
if '.html' == fname[-5:]:
if self.analyze(fname, find_sources, check_remote):
@@ -372,7 +387,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.site, self.cache)

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

def clean_files(self):
"""Remove orphaned files."""
only_on_output, _ = real_scan_files(self.site)
only_on_output, _ = real_scan_files(self.site, self.cache)
for f in only_on_output:
self.logger.info('removed: {0}'.format(f))
os.unlink(f)
2 changes: 2 additions & 0 deletions nikola/plugins/task/posts.py
Original file line number Diff line number Diff line change
@@ -77,6 +77,8 @@ def tl_ch():
deps_dict = copy(kw)
deps_dict.pop('timeline')
for post in kw['timeline']:
if not post.is_translation_available(lang) and not self.site.config['SHOW_UNTRANSLATED_POSTS']:
continue
# Extra config dependencies picked from config
for p in post.fragment_deps(lang):
if p.startswith('####MAGIC####CONFIG:'):
20 changes: 10 additions & 10 deletions nikola/plugins/task/tags.py
Original file line number Diff line number Diff line change
@@ -401,7 +401,7 @@ def tag_index_path(self, name, lang):
link://tag_index => /tags/index.html
"""
return [_f for _f in [self.site.config['TRANSLATIONS'][lang],
self.site.config['TAG_PATH'],
self.site.config['TAG_PATH'][lang],
self.site.config['INDEX_FILE']] if _f]

def category_index_path(self, name, lang):
@@ -412,7 +412,7 @@ def category_index_path(self, name, lang):
link://category_index => /categories/index.html
"""
return [_f for _f in [self.site.config['TRANSLATIONS'][lang],
self.site.config['CATEGORY_PATH'],
self.site.config['CATEGORY_PATH'][lang],
self.site.config['INDEX_FILE']] if _f]

def tag_path(self, name, lang):
@@ -425,13 +425,13 @@ def tag_path(self, name, lang):
if self.site.config['PRETTY_URLS']:
return [_f for _f in [
self.site.config['TRANSLATIONS'][lang],
self.site.config['TAG_PATH'],
self.site.config['TAG_PATH'][lang],
self.slugify_tag_name(name),
self.site.config['INDEX_FILE']] if _f]
else:
return [_f for _f in [
self.site.config['TRANSLATIONS'][lang],
self.site.config['TAG_PATH'],
self.site.config['TAG_PATH'][lang],
self.slugify_tag_name(name) + ".html"] if _f]

def tag_atom_path(self, name, lang):
@@ -442,7 +442,7 @@ def tag_atom_path(self, name, lang):
link://tag_atom/cats => /tags/cats.atom
"""
return [_f for _f in [self.site.config['TRANSLATIONS'][lang],
self.site.config['TAG_PATH'], self.slugify_tag_name(name) + ".atom"] if
self.site.config['TAG_PATH'][lang], self.slugify_tag_name(name) + ".atom"] if
_f]

def tag_rss_path(self, name, lang):
@@ -453,7 +453,7 @@ def tag_rss_path(self, name, lang):
link://tag_rss/cats => /tags/cats.xml
"""
return [_f for _f in [self.site.config['TRANSLATIONS'][lang],
self.site.config['TAG_PATH'], self.slugify_tag_name(name) + ".xml"] if
self.site.config['TAG_PATH'][lang], self.slugify_tag_name(name) + ".xml"] if
_f]

def slugify_category_name(self, name):
@@ -480,11 +480,11 @@ def category_path(self, name, lang):
"""
if self.site.config['PRETTY_URLS']:
return [_f for _f in [self.site.config['TRANSLATIONS'][lang],
self.site.config['CATEGORY_PATH']] if
self.site.config['CATEGORY_PATH'][lang]] if
_f] + self.slugify_category_name(name) + [self.site.config['INDEX_FILE']]
else:
return [_f for _f in [self.site.config['TRANSLATIONS'][lang],
self.site.config['CATEGORY_PATH']] if
self.site.config['CATEGORY_PATH'][lang]] if
_f] + self._add_extension(self.slugify_category_name(name), ".html")

def category_atom_path(self, name, lang):
@@ -495,7 +495,7 @@ def category_atom_path(self, name, lang):
link://category_atom/dogs => /categories/dogs.atom
"""
return [_f for _f in [self.site.config['TRANSLATIONS'][lang],
self.site.config['CATEGORY_PATH']] if
self.site.config['CATEGORY_PATH'][lang]] if
_f] + self._add_extension(self.slugify_category_name(name), ".atom")

def category_rss_path(self, name, lang):
@@ -506,5 +506,5 @@ def category_rss_path(self, name, lang):
link://category_rss/dogs => /categories/dogs.xml
"""
return [_f for _f in [self.site.config['TRANSLATIONS'][lang],
self.site.config['CATEGORY_PATH']] if
self.site.config['CATEGORY_PATH'][lang]] if
_f] + self._add_extension(self.slugify_category_name(name), ".xml")
25 changes: 8 additions & 17 deletions nikola/post.py
Original file line number Diff line number Diff line change
@@ -56,7 +56,6 @@
# for tearDown with _reload we cannot use 'from import' to get forLocaleBorg
import nikola.utils
from .utils import (
bytes_str,
current_time,
Functionary,
LOGGER,
@@ -324,19 +323,7 @@ def template_name(self):

def formatted_date(self, date_format, date=None):
"""Return the formatted date as unicode."""
date = date if date else self.date

if date_format == 'webiso':
# Formatted after RFC 3339 (web ISO 8501 profile) with Zulu
# zone desgignator for times in UTC and no microsecond precision.
fmt_date = date.replace(microsecond=0).isoformat().replace('+00:00', 'Z')
else:
fmt_date = date.strftime(date_format)

# Issue #383, this changes from py2 to py3
if isinstance(fmt_date, bytes_str):
fmt_date = fmt_date.decode('utf8')
return fmt_date
return utils.formatted_date(date_format, date if date else self.date)

def formatted_updated(self, date_format):
"""Return the updated date as unicode."""
@@ -781,12 +768,16 @@ def section_slug(self, lang=None):
if dest[-(1 + len(self.index_file)):] == '/' + self.index_file:
dest = dest[:-(1 + len(self.index_file))]
dirname = os.path.dirname(dest)
slug = dirname
if not dirname or dirname == '.':
slug = dest.split(os.sep)
if not slug or dirname == '.':
slug = self.messages[lang]["Uncategorized"]
elif lang == slug[0]:
slug = slug[1]
else:
slug = slug[0]
else:
slug = self.meta[lang]['section'].split(',')[0] if 'section' in self.meta[lang] else self.messages[lang]["Uncategorized"]
return slug.replace(' ', '-').lower()
return utils.slugify(slug)

def permalink(self, lang=None, absolute=False, extension='.html', query=None):
"""Return permalink for a post."""
Loading