Bladeren bron

Added plugin: pelican comment system

Bernhard Scheirle 10 jaren geleden
bovenliggende
commit
20f8a24971

+ 110 - 0
pelican_comment_system/Readme.md

@@ -0,0 +1,110 @@
+# Pelican comment system
+The pelican comment system allows you to add static comments to your articles. It also supports replies to comments.
+
+The comments are stored in Markdown files. Each comment in it own file.
+
+See it in action here: [blog.scheirle.de](http://blog.scheirle.de/posts/2014/March/29/static-comments-via-email/)
+
+Thanks to jesrui the author of [Static comments](https://github.com/getpelican/pelican-plugins/tree/master/static_comments). I reused some code from it.
+
+## Installation
+Activate the plugin by adding it you your `pelicanconf.py`
+
+	PLUGIN_PATH = '/path/to/pelican-plugins'
+	PLUGINS = ['pelican_comment_system']
+	PELICAN_COMMENT_SYSTEM = True
+
+And modify your `article.html` theme (see below).
+
+## Settings
+Name                         | Type      | Default    | Description
+-----------------------------|-----------|------------|-------
+`PELICAN_COMMENT_SYSTEM`     | `boolean` | `False`    | Activates or deactivates the comment system
+`PELICAN_COMMENT_SYSTEM_DIR` | `string`  | `comments` | Folder where the comments are stored
+
+
+### Folder structure
+Every comment file has to be stored in a sub folder of `PELICAN_COMMENT_SYSTEM_DIR`.
+Sub folders are named after the `slug` of the articles.
+
+So the comments to your `foo-bar` article are stored in `comments/foo-bar/`
+
+The filenames of the comment files are up to you. But the filename is the Identifier of the comment (without extension).
+
+##### Example folder structure
+
+	.
+	└── comments
+		└── foo-bar
+		│   ├── 1.md
+		│   └── 0.md
+		└── some-other-slug
+			├── random-Name.md
+			├── 1.md
+			└── 0.md
+
+
+### Comment file
+##### Meta information
+Tag           | Required  | Description
+--------------|-----------|----------------
+`date`        | yes       | Date when the comment was posted
+`replyto`     | no        | Identifier of the parent comment. Identifier = Filename (without extension)
+`locale_date` | forbidden | Will be overwritten with a locale representation of the date
+
+Every other (custom) tag gets parsed as well and will be available through the theme.
+
+
+##### Example of a comment file
+
+	date: 2014-3-21 15:02
+	author: Author of the comment
+	website: http://authors.website.com
+	replyto: 7
+	anothermetatag: some random tag
+
+	Content of the comment.
+
+### Theme
+In the `article.html` theme file are now two more variables available.
+
+Variables                         | Description
+----------------------------------|--------------------------
+`article.metadata.comments_count` | Amount of total comments for this article (including replies to comments)
+`article.metadata.comments`       | Array containing the top level comments for this article (no replies to comments)
+
+#### Comment object
+Variables  | Description
+-----------|--------------------------
+`id`       | Identifier of this comment
+`content`  | Content of this comment
+`metadata` | All metadata as in the comment file (or described above)
+`replies`  | Array containing the top level replies for this comment
+
+##### Example article.html theme
+(only the comment section)
+
+```html
+{% if article.metadata.comments %}
+	{% for comment in article.metadata.comments recursive %}
+		{% set metadata = comment.metadata %}
+		{% if loop.depth0 == 0 %}
+			{% set marginLeft = 0 %}
+		{% else %}
+			{% set marginLeft = 50 %}
+		{% endif %}
+			<article id="comment-{{comment.id}}" style="border: 1px solid #DDDDDD; padding: 5px 0px 0px 5px; margin: 0px -1px 5px {{marginLeft}}px;">
+				<a href="{{ SITEURL }}/{{ article.url }}#comment-{{comment.id}}" rel="bookmark" title="Permalink to this comment">Permalink</a>
+				<h4>{{ metadata['author'] }}</h4>
+				<p>Posted on <abbr class="published" title="{{ metadata['date'].isoformat() }}">{{ metadata['locale_date'] }}</abbr></p>
+
+				{{ comment.content }}
+				{% if comment.replies %}
+					{{ loop(comment.replies) }}
+				{% endif %}
+			</article>
+	{% endfor %}
+{% else %}
+	<p>There are no comments yet.<p>
+{% endif %}
+```

+ 1 - 0
pelican_comment_system/__init__.py

@@ -0,0 +1 @@
+from .pelican_comment_system import *

+ 104 - 0
pelican_comment_system/pelican_comment_system.py

@@ -0,0 +1,104 @@
+# -*- coding: utf-8 -*-
+
+import logging
+import os
+
+logger = logging.getLogger(__name__)
+
+from itertools import chain
+from pelican import signals
+from pelican.utils import strftime
+from pelican.readers import MarkdownReader
+
+class Comment:
+	def __init__(self, id, metadata, content):
+		self.id = id
+		self.content = content
+		self.metadata = metadata
+		self.replies = []
+
+	def addReply(self, comment):
+		self.replies.append(comment)
+
+	def getReply(self, id):
+		for reply in self.replies:
+			if reply.id == id:
+				return reply
+			else:
+				deepReply = reply.getReply(id)
+				if deepReply != None:
+					return deepReply
+		return None
+
+	def __lt__(self, other):
+		return self.metadata['date'] < other.metadata['date']
+
+	def sort(self):
+		for r in self.replies:
+			r.sort()
+		self.replies = sorted(self.replies)
+
+	def countReplies(self):
+		amount = 0
+		for r in self.replies:
+			amount += r.countReplies()
+		return amount + len(self.replies)
+
+def initialized(pelican):
+	from pelican.settings import DEFAULT_CONFIG
+	DEFAULT_CONFIG.setdefault('PELICAN_COMMENT_SYSTEM', False)
+	DEFAULT_CONFIG.setdefault('PELICAN_COMMENT_SYSTEM_DIR' 'comments')
+	if pelican:
+		pelican.settings.setdefault('PELICAN_COMMENT_SYSTEM', False)
+		pelican.settings.setdefault('PELICAN_COMMENT_SYSTEM_DIR', 'comments')
+
+
+def add_static_comments(gen, metadata):
+	if gen.settings['PELICAN_COMMENT_SYSTEM'] != True:
+		return
+
+	metadata['comments_count'] = 0
+	metadata['comments'] = []
+
+	if not 'slug' in metadata:
+		logger.warning("pelican_comment_system: cant't locate comments files without slug tag in the article")
+		return
+
+	reader = MarkdownReader(gen.settings)
+	comments = []
+	replies = []
+	folder = os.path.join(gen.settings['PELICAN_COMMENT_SYSTEM_DIR'], metadata['slug'])
+
+	if not os.path.isdir(folder):
+		logger.debug("No comments found for: " + metadata['slug'])
+		return
+
+	for file in os.listdir(folder):
+		name, extension = os.path.splitext(file)
+		if extension[1:].lower() in reader.file_extensions:
+			content, meta = reader.read(folder + "/" + file)
+			meta['locale_date'] = strftime(meta['date'], gen.settings['DEFAULT_DATE_FORMAT'])
+			com = Comment(name, meta, content)
+			if 'replyto' in meta:
+				replies.append( com )
+			else:
+				comments.append( com )
+
+	for reply in replies:
+		for comment in chain(comments, replies):
+			if comment.id == reply.metadata['replyto']:
+				comment.addReply(reply)
+
+	count = 0
+	for comment in comments:
+		comment.sort()
+		count += comment.countReplies()
+
+	comments = sorted(comments)
+
+	metadata['comments_count'] = len(comments) + count
+	metadata['comments'] = comments
+
+def register():
+	signals.initialized.connect(initialized)
+	signals.article_generator_context.connect(add_static_comments)