diff options
| author | 2016-11-15 14:18:46 -0300 | |
|---|---|---|
| committer | 2016-11-15 14:18:46 -0300 | |
| commit | ffb671c61a24a9086343b54bad080e145ff33fc5 (patch) | |
| tree | 2c5291f7a34edf4afdc8e07887a148291bfa3fa1 /nikola/post.py | |
| parent | 4e3224c012df9f74f010eb92203520515e8537b9 (diff) | |
New upstream version 7.8.1upstream/7.8.1
Diffstat (limited to 'nikola/post.py')
| -rw-r--r-- | nikola/post.py | 88 |
1 files changed, 68 insertions, 20 deletions
diff --git a/nikola/post.py b/nikola/post.py index f8039e0..37e4241 100644 --- a/nikola/post.py +++ b/nikola/post.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- -# Copyright © 2012-2015 Roberto Alsina and others. +# Copyright © 2012-2016 Roberto Alsina and others. # Permission is hereby granted, free of charge, to any # person obtaining a copy of this software and associated @@ -43,6 +43,7 @@ except ImportError: from . import utils +from blinker import signal import dateutil.tz import lxml.html import natsort @@ -51,7 +52,7 @@ try: except ImportError: pyphen = None -from math import ceil +from math import ceil # for reading time feature # for tearDown with _reload we cannot use 'from import' to get forLocaleBorg import nikola.utils @@ -109,7 +110,6 @@ class Post(object): self.base_url = self.config['BASE_URL'] self.is_draft = False self.is_private = False - self.is_mathjax = False self.strip_indexes = self.config['STRIP_INDEXES'] self.index_file = self.config['INDEX_FILE'] self.pretty_urls = self.config['PRETTY_URLS'] @@ -136,6 +136,7 @@ class Post(object): self._dependency_file_page = defaultdict(list) self._dependency_uptodate_fragment = defaultdict(list) self._dependency_uptodate_page = defaultdict(list) + self._depfile = defaultdict(list) default_metadata, self.newstylemeta = get_meta(self, self.config['FILE_METADATA_REGEXP'], self.config['UNSLUGIFY_TITLES']) @@ -160,8 +161,14 @@ class Post(object): for lang in sorted(self.translated_to): default_metadata.update(self.meta[lang]) + # Load data field from metadata + self.data = Functionary(lambda: None, self.default_lang) + for lang in self.translations: + if self.meta[lang].get('data') is not None: + self.data[lang] = utils.load_data(self.meta[lang]['data']) + if 'date' not in default_metadata and not use_in_feeds: - # For stories we don't *really* need a date + # For pages we don't *really* need a date if self.config['__invariant__']: default_metadata['date'] = datetime.datetime(2013, 12, 31, 23, 59, 59, tzinfo=tzinfo) else: @@ -169,7 +176,10 @@ class Post(object): os.stat(self.source_path).st_ctime).replace(tzinfo=dateutil.tz.tzutc()).astimezone(tzinfo) # If time zone is set, build localized datetime. - self.date = to_datetime(self.meta[self.default_lang]['date'], tzinfo) + try: + self.date = to_datetime(self.meta[self.default_lang]['date'], tzinfo) + except ValueError: + raise ValueError("Invalid date '{0}' in file {1}".format(self.meta[self.default_lang]['date'], source_path)) if 'updated' not in default_metadata: default_metadata['updated'] = default_metadata.get('date', None) @@ -178,12 +188,11 @@ class Post(object): if 'title' not in default_metadata or 'slug' not in default_metadata \ or 'date' not in default_metadata: - raise OSError("You must set a title (found '{0}'), a slug (found " - "'{1}') and a date (found '{2}')! [in file " - "{3}]".format(default_metadata.get('title', None), - default_metadata.get('slug', None), - default_metadata.get('date', None), - source_path)) + raise ValueError("You must set a title (found '{0}'), a slug (found '{1}') and a date (found '{2}')! " + "[in file {3}]".format(default_metadata.get('title', None), + default_metadata.get('slug', None), + default_metadata.get('date', None), + source_path)) if 'type' not in default_metadata: # default value is 'text' @@ -223,9 +232,6 @@ class Post(object): self.use_in_feeds = use_in_feeds and not is_draft and not is_private \ and not self.publish_later - # If mathjax is a tag, or it's a ipynb post, then enable mathjax rendering support - self.is_mathjax = ('mathjax' in self.tags) or (self.compiler.name == 'ipynb') - # Register potential extra dependencies self.compiler.register_extra_dependencies(self) @@ -259,6 +265,17 @@ class Post(object): return False @property + def is_mathjax(self): + """True if this post has the mathjax tag in the current language or is a python notebook.""" + if self.compiler.name == 'ipynb': + return True + lang = nikola.utils.LocaleBorg().current_lang + if self.is_translation_available(lang): + return 'mathjax' in self.tags_for_language(lang) + # If it has math in ANY other language, enable it. Better inefficient than broken. + return 'mathjax' in self.alltags + + @property def alltags(self): """Return ALL the tags for this post.""" tags = [] @@ -416,6 +433,24 @@ class Post(object): if add == 'page' or add == 'both': self._dependency_uptodate_page[lang].append((is_callable, dependency)) + def register_depfile(self, dep, dest=None, lang=None): + """Register a dependency in the dependency file.""" + if not dest: + dest = self.translated_base_path(lang) + self._depfile[dest].append(dep) + + @staticmethod + def write_depfile(dest, deps_list): + """Write a depfile for a given language.""" + deps_path = dest + '.dep' + if deps_list: + deps_list = [p for p in deps_list if p != dest] # Don't depend on yourself (#1671) + with io.open(deps_path, "w+", encoding="utf8") as deps_file: + deps_file.write('\n'.join(deps_list)) + else: + if os.path.isfile(deps_path): + os.unlink(deps_path) + def _get_dependencies(self, deps_list): deps = [] for dep in deps_list: @@ -448,6 +483,8 @@ class Post(object): cand_3 = get_translation_candidate(self.config, self.metadata_path, lang) if os.path.exists(cand_3): deps.append(cand_3) + if self.meta('data', lang): + deps.append(self.meta('data', lang)) deps += self._get_dependencies(self._dependency_file_page[lang]) deps += self._get_dependencies(self._dependency_file_page[None]) return sorted(deps) @@ -482,7 +519,15 @@ class Post(object): self.compile_html( self.translated_source_path(lang), dest, - self.is_two_file), + self.is_two_file) + Post.write_depfile(dest, self._depfile[dest]) + + signal('compiled').send({ + 'source': self.translated_source_path(lang), + 'dest': dest, + 'post': self, + }) + if self.meta('password'): # TODO: get rid of this feature one day (v8?; warning added in v7.3.0.) LOGGER.warn("The post {0} is using the `password` attribute, which may stop working in the future.") @@ -788,7 +833,7 @@ class Post(object): slug = slug[0] else: slug = self.meta[lang]['section'].split(',')[0] if 'section' in self.meta[lang] else self.messages[lang]["Uncategorized"] - return utils.slugify(slug) + return utils.slugify(slug, lang) def permalink(self, lang=None, absolute=False, extension='.html', query=None): """Return permalink for a post.""" @@ -864,7 +909,7 @@ def re_meta(line, match=None): return (None,) -def _get_metadata_from_filename_by_regex(filename, metadata_regexp, unslugify_titles): +def _get_metadata_from_filename_by_regex(filename, metadata_regexp, unslugify_titles, lang): """Try to reed the metadata from the filename based on the given re. This requires to use symbolic group names in the pattern. @@ -879,7 +924,7 @@ def _get_metadata_from_filename_by_regex(filename, metadata_regexp, unslugify_ti for key, value in match.groupdict().items(): k = key.lower().strip() # metadata must be lowercase if k == 'title' and unslugify_titles: - meta[k] = unslugify(value, discard_numbers=False) + meta[k] = unslugify(value, lang, discard_numbers=False) else: meta[k] = value @@ -1043,7 +1088,8 @@ def get_meta(post, file_metadata_regexp=None, unslugify_titles=False, lang=None) if file_metadata_regexp is not None: meta.update(_get_metadata_from_filename_by_regex(post.source_path, file_metadata_regexp, - unslugify_titles)) + unslugify_titles, + post.default_lang)) compiler_meta = {} @@ -1062,7 +1108,7 @@ def get_meta(post, file_metadata_regexp=None, unslugify_titles=False, lang=None) if 'slug' not in meta: # If no slug is found in the metadata use the filename meta['slug'] = slugify(unicode_str(os.path.splitext( - os.path.basename(post.source_path))[0])) + os.path.basename(post.source_path))[0]), post.default_lang) if 'title' not in meta: # If no title is found, use the filename without extension @@ -1081,6 +1127,7 @@ def hyphenate(dom, _lang): lang = LEGAL_VALUES['PYPHEN_LOCALES'].get(_lang, pyphen.language_fallback(_lang)) else: utils.req_missing(['pyphen'], 'hyphenate texts', optional=True) + hyphenator = None if pyphen is not None and lang is not None: # If pyphen does exist, we tell the user when configuring the site. # If it does not support a language, we ignore it quietly. @@ -1089,6 +1136,7 @@ def hyphenate(dom, _lang): except KeyError: LOGGER.error("Cannot find hyphenation dictoniaries for {0} (from {1}).".format(lang, _lang)) LOGGER.error("Pyphen cannot be installed to ~/.local (pip install --user).") + if hyphenator is not None: for tag in ('p', 'li', 'span'): for node in dom.xpath("//%s[not(parent::pre)]" % tag): skip_node = False |
