{{ metadata['author'] }}
+Posted on {{ metadata['locale_date'] }}
+ + {{ comment.content }} + {% if comment.replies %} + {{ loop(comment.replies) }} + {% endif %} +diff --git a/pelican_comment_system/Readme.md b/pelican_comment_system/Readme.md
new file mode 100644
index 0000000..441cbab
--- /dev/null
+++ b/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 %}
+ Posted on {{ metadata['locale_date'] }}{{ metadata['author'] }}
+
There are no comments yet.
+{% endif %} +``` diff --git a/pelican_comment_system/__init__.py b/pelican_comment_system/__init__.py new file mode 100644 index 0000000..4c8a3ca --- /dev/null +++ b/pelican_comment_system/__init__.py @@ -0,0 +1 @@ +from .pelican_comment_system import * diff --git a/pelican_comment_system/pelican_comment_system.py b/pelican_comment_system/pelican_comment_system.py new file mode 100644 index 0000000..bf281bf --- /dev/null +++ b/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)