diff options
Diffstat (limited to 'nikola/post.py')
| -rw-r--r-- | nikola/post.py | 180 |
1 files changed, 180 insertions, 0 deletions
diff --git a/nikola/post.py b/nikola/post.py new file mode 100644 index 0000000..9b2d73f --- /dev/null +++ b/nikola/post.py @@ -0,0 +1,180 @@ +# -*- coding: utf-8 -*- + +import codecs +import os + +import lxml.html + +import utils + +__all__ = ['Post'] + + +class Post(object): + + """Represents a blog post or web page.""" + + def __init__(self, source_path, destination, use_in_feeds, + translations, default_lang, blog_url, compile_html, messages): + """Initialize post. + + The base path is the .txt post file. From it we calculate + the meta file, as well as any translations available, and + the .html fragment file path. + + `compile_html` is a function that knows how to compile this Post to + html. + """ + self.prev_post = None + self.next_post = None + self.blog_url = blog_url + self.is_draft = False + self.source_path = source_path # posts/blah.txt + self.post_name = os.path.splitext(source_path)[0] # posts/blah + # cache/posts/blah.html + self.base_path = os.path.join('cache', self.post_name + ".html") + self.metadata_path = self.post_name + ".meta" # posts/blah.meta + self.folder = destination + self.translations = translations + self.default_lang = default_lang + self.messages = messages + if os.path.isfile(self.metadata_path): + with codecs.open(self.metadata_path, "r", "utf8") as meta_file: + meta_data = meta_file.readlines() + while len(meta_data) < 6: + meta_data.append("") + (default_title, default_pagename, self.date, self.tags, + self.link, default_description) = \ + [x.strip() for x in meta_data][:6] + else: + (default_title, default_pagename, self.date, self.tags, + self.link, default_description) = \ + utils.get_meta(self.source_path) + + if not default_title or not default_pagename or not self.date: + raise OSError("You must set a title and slug and date!") + + self.date = utils.to_datetime(self.date) + self.tags = [x.strip() for x in self.tags.split(',')] + self.tags = filter(None, self.tags) + + # While draft comes from the tags, it's not really a tag + self.use_in_feeds = use_in_feeds and "draft" not in self.tags + self.is_draft = 'draft' in self.tags + self.tags = [t for t in self.tags if t != 'draft'] + + self.compile_html = compile_html + + self.pagenames = {} + self.titles = {} + self.descriptions = {} + # Load internationalized titles + # TODO: this has gotten much too complicated. Rethink. + for lang in translations: + if lang == default_lang: + self.titles[lang] = default_title + self.pagenames[lang] = default_pagename + self.descriptions[lang] = default_description + else: + metadata_path = self.metadata_path + "." + lang + source_path = self.source_path + "." + lang + try: + if os.path.isfile(metadata_path): + with codecs.open( + metadata_path, "r", "utf8") as meta_file: + meta_data = [x.strip() for x in + meta_file.readlines()] + while len(meta_data) < 6: + meta_data.append("") + self.titles[lang] = meta_data[0] or default_title + self.pagenames[lang] = meta_data[1] or\ + default_pagename + self.descriptions[lang] = meta_data[5] or\ + default_description + else: + ttitle, ppagename, tmp1, tmp2, tmp3, ddescription = \ + utils.get_meta(source_path) + self.titles[lang] = ttitle or default_title + self.pagenames[lang] = ppagename or default_pagename + self.descriptions[lang] = ddescription or\ + default_description + except: + self.titles[lang] = default_title + self.pagenames[lang] = default_pagename + self.descriptions[lang] = default_description + + def title(self, lang): + """Return localized title.""" + return self.titles[lang] + + def description(self, lang): + """Return localized description.""" + return self.descriptions[lang] + + def deps(self, lang): + """Return a list of dependencies to build this post's page.""" + deps = [self.base_path] + if lang != self.default_lang: + deps += [self.base_path + "." + lang] + deps += self.fragment_deps(lang) + return deps + + def fragment_deps(self, lang): + """Return a list of dependencies to build this post's fragment.""" + deps = [self.source_path] + if os.path.isfile(self.metadata_path): + deps.append(self.metadata_path) + if lang != self.default_lang: + lang_deps = filter(os.path.exists, [x + "." + lang for x in deps]) + deps += lang_deps + return deps + + def text(self, lang, teaser_only=False): + """Read the post file for that language and return its contents""" + file_name = self.base_path + if lang != self.default_lang: + file_name_lang = file_name + ".%s" % lang + if os.path.exists(file_name_lang): + file_name = file_name_lang + with codecs.open(file_name, "r", "utf8") as post_file: + data = post_file.read() + + if data: + data = lxml.html.make_links_absolute(data, self.permalink()) + if data and teaser_only: + e = lxml.html.fromstring(data) + teaser = [] + flag = False + for elem in e: + elem_string = lxml.html.tostring(elem) + if '<!-- TEASER_END -->' in elem_string.upper(): + flag = True + break + teaser.append(elem_string) + if flag: + teaser.append('<p><a href="%s">%s...</a></p>' % + (self.permalink(lang), self.messages[lang]["Read more"])) + data = ''.join(teaser) + return data + + def destination_path(self, lang, extension='.html'): + path = os.path.join(self.translations[lang], + self.folder, self.pagenames[lang] + extension) + return path + + def permalink(self, lang=None, absolute=False, extension='.html'): + if lang is None: + lang = self.default_lang + pieces = list(os.path.split(self.translations[lang])) + pieces += list(os.path.split(self.folder)) + pieces += [self.pagenames[lang] + extension] + pieces = filter(None, pieces) + if absolute: + pieces = [self.blog_url] + pieces + else: + pieces = [""] + pieces + link = "/".join(pieces) + return link + + def source_ext(self): + return os.path.splitext(self.source_path)[1] |
