Permalink
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Browse files
Merge pull request #79 from getnikola/new-recent-posts-json
New plug-in: Recent posts as JSON
- Loading branch information
Showing
with
155 additions
and 0 deletions.
@@ -0,0 +1,23 @@ | ||
This plug-in generates a /index.json file containing the same posts | ||
as /index.html. Intended to be used in JavaScripts. For example to | ||
promote the most recent posts at the bottom of older posts. | ||
|
||
By default, the JSON file will include: | ||
[ | ||
{ | ||
"date": <JS Date object>, | ||
"title": <post-title>, | ||
"loc": <relative-link-to-post> | ||
}, | ||
] | ||
|
||
Optionally, it can be expanded to include thumbnails or descriptions: | ||
[ { | ||
"date" <JS Date object>, "title": <post-title>, "loc": <post-relative-link>, | ||
"desc": <post-meta-description>, | ||
"img": <post-meta-thumbnail> | ||
], } | ||
|
||
Posts are sorted by their post.meta.date as JavaScript dates. | ||
|
||
Pro tip: Set a sensible cache header for the JSON file. |
@@ -0,0 +1,11 @@ | ||
# Generates a /index.json with the most recent posts from /index.html. | ||
# Can be expanded with these options: | ||
|
||
# Number of posts to include, defaults to INDEX_DISPLAY_POST_COUNT (10) | ||
RECENT_POSTS_JSON_LENGTH = 5 | ||
|
||
# Include {"desc": post.description}, defaults to False | ||
RECENT_POSTS_JSON_DESCRIPTION = False | ||
|
||
# Include {"img": post.meta.previewimage}, defaults to False | ||
RECENT_POSTS_JSON_PREVIEWIMAGE = False |
@@ -0,0 +1,10 @@ | ||
[Core] | ||
Name = recent_posts_json | ||
Module = recent_posts_json | ||
|
||
[Documentation] | ||
Author = Daniel Aleksandersen | ||
Version = 0.9.0 | ||
Website = https://www.aeyoun.com | ||
Description = Generate JSON with recent posts. | ||
|
@@ -0,0 +1,111 @@ | ||
# -*- coding: utf-8 -*- | ||
|
||
# Copyright © 2012-2015 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 unicode_literals, print_function | ||
import os | ||
import io | ||
import json | ||
import time | ||
try: | ||
from urlparse import urljoin | ||
except ImportError: | ||
from urllib.parse import urljoin # NOQA | ||
|
||
from nikola import utils | ||
from nikola.plugin_categories import Task | ||
|
||
|
||
class RecentPostsJon(Task): | ||
"""Generate JSON with recent posts.""" | ||
|
||
name = "recent_posts_json" | ||
|
||
def set_site(self, site): | ||
site.register_path_handler("recent_posts_json", self.json_path) | ||
return super(RecentPostsJon, self).set_site(site) | ||
|
||
def gen_tasks(self): | ||
"""Generate RSS feeds.""" | ||
kw = { | ||
"output_folder": self.site.config["OUTPUT_FOLDER"], | ||
"filters": self.site.config["FILTERS"], | ||
"index_file": self.site.config["INDEX_FILE"], | ||
"translations": self.site.config["TRANSLATIONS"], | ||
"show_untranslated_posts": self.site.config["SHOW_UNTRANSLATED_POSTS"], | ||
"site_url": self.site.config["SITE_URL"], | ||
"base_url": self.site.config["BASE_URL"], | ||
"json_posts_length": self.site.config["RECENT_POSTS_JSON_LENGTH"] if "RECENT_POSTS_JSON_LENGTH" in self.site.config else self.site.config["INDEX_DISPLAY_POST_COUNT"], | ||
"json_descriptions": self.site.config["RECENT_POSTS_JSON_DESCRIPTION"] if "RECENT_POSTS_JSON_DESCRIPTION" in self.site.config else False, | ||
"json_previewimage": self.site.conf["RECENT_POSTS_JSON_PREVIEWIMAGE"] if "RECENT_POSTS_JSON_PREVIEWIMAGE" in self.site.config else False, | ||
} | ||
self.site.scan_posts() | ||
yield self.group_task() | ||
for lang in kw["translations"]: | ||
output_path = os.path.join(kw["output_folder"], | ||
self.site.path("recent_posts_json", None, lang)) | ||
deps = [] | ||
deps_uptodate = [] | ||
if kw["show_untranslated_posts"]: | ||
posts = self.site.posts[:kw["json_posts_length"]] | ||
else: | ||
posts = [x for x in self.site.posts if x.is_translation_available(lang)][:kw["json_posts_length"]] | ||
for post in posts: | ||
deps += post.deps(lang) | ||
deps_uptodate += post.deps_uptodate(lang) | ||
task = { | ||
"basename": "recent_posts_json", | ||
"name": os.path.normpath(output_path), | ||
"file_dep": deps, | ||
"targets": [output_path], | ||
"actions": [(self.make_json, | ||
(posts, kw["json_descriptions"], kw["json_previewimage"], output_path))], | ||
"task_dep": ["render_posts"], | ||
"clean": True, | ||
"uptodate": [utils.config_changed(kw, "nikola.plugins.task.recent_pots_json")] + deps_uptodate, | ||
} | ||
yield utils.apply_filters(task, kw["filters"]) | ||
|
||
def make_json(self, posts, descriptions, previewimage, output_path): | ||
recent_posts = [] | ||
for post in posts: | ||
date = int(time.mktime(post.date.timetuple()) * 1000) # JavaScript Date | ||
link = post.permalink(absolute=False) | ||
title = post.title() | ||
entry = {"date": date, | ||
"title": title, | ||
"loc": link} | ||
if descriptions: | ||
entry.update({["desc"]: post.description()}) | ||
if previewimage: | ||
entry.update({["img"]: post.previewimage()}) | ||
recent_posts.append(entry) | ||
data = json.dumps(recent_posts, indent=2) | ||
with io.open(output_path, "w+", encoding="utf8") as outf: | ||
outf.write(data) | ||
|
||
def json_path(self, name, lang): | ||
return [_f for _f in [self.site.config["TRANSLATIONS"][lang], | ||
os.path.splitext(self.site.config["INDEX_FILE"])[0] + ".json"] if _f] |