Enabled multiple posting of a document (issue #4).

This commit is contained in:
Ahmet Bakan 2014-07-29 23:01:19 -07:00
parent 68e4f29f27
commit 416d089343
6 changed files with 142 additions and 100 deletions

View file

@ -10,12 +10,20 @@ from .post import (PostDirective, PostListDirective,
__version__ = '0.1' __version__ = '0.1'
def anchor(post):
if post.section:
return '#' + post.section
else:
return ''
def init_ablog(app): def init_ablog(app):
"""Instantiate ABlog and link from `html_context` so that it can be """Instantiate ABlog and link from `html_context` so that it can be
reached from templates.""" reached from templates."""
app.config.html_context['ablog'] = Blog(app) app.config.html_context['ablog'] = Blog(app)
app.config.html_context['anchor'] = anchor
def setup(app): def setup(app):
"""Setup ABlog extension.""" """Setup ABlog extension."""

View file

@ -209,7 +209,7 @@ class Blog(object):
def link_posts(self): def link_posts(self):
"""Link posts after sorting them post by published date.""" """Link posts after sorting them post by published date."""
posts = list(self.posts) posts = [post for post in self.posts if post.order == 1]
posts.sort() posts.sort()
posts[0].prev = posts[-1].next = None posts[0].prev = posts[-1].next = None
for i in range(1, len(posts)): for i in range(1, len(posts)):
@ -262,6 +262,8 @@ class Post(object):
self.ablog = ablog self.ablog = ablog
self.docname = docname self.docname = docname
self.section = info['section']
self.order = info['order']
self.date = date = info['date'] self.date = date = info['date']
self.update = info['update'] self.update = info['update']
self.published = date and date < TOMORROW self.published = date and date < TOMORROW
@ -465,7 +467,10 @@ class Collection(object):
def add(self, post): def add(self, post):
"""Add post to the collection.""" """Add post to the collection."""
self._posts[post.docname] = post post_name = post.docname
if post.section:
post_name += '#' + post.section
self._posts[post_name] = post
@property @property
def relsize(self): def relsize(self):

View file

@ -11,7 +11,7 @@ from sphinx.util.compat import Directive
from docutils.parsers.rst import directives from docutils.parsers.rst import directives
import ablog import ablog
from .blog import Blog from .blog import Blog, slugify
class PostNode(nodes.Element): class PostNode(nodes.Element):
"""Represent ``post`` directive content and options in document tree.""" """Represent ``post`` directive content and options in document tree."""
@ -129,18 +129,26 @@ def process_posts(app, doctree):
# "document isn't included in any toctree" warning is not issued # "document isn't included in any toctree" warning is not issued
app.env.metadata[docname]['orphan'] = True app.env.metadata[docname]['orphan'] = True
blog = Blog(app)
multi_post = len(post_nodes) > 1
for order, node in enumerate(post_nodes, start=1):
node = post_nodes[0] if multi_post:
# section title, and first few paragraphs of the section of post
# are used when there are more than 1 posts
section = node
while True:
if isinstance(section, nodes.section):
break
section = node.parent
else:
section = doctree
if len(post_nodes) > 1:
env.warn(docname, 'multiple post directives found, '
'first one is considered')
#from code import interact; interact(local=locals())
# Making sure that post has a title because all post titles # Making sure that post has a title because all post titles
# are needed when resolving post lists in documents # are needed when resolving post lists in documents
title = node['title'] title = node['title']
if not title: if not title:
for title in doctree.traverse(nodes.title): for title in section.traverse(nodes.title):
break break
# A problem with the following is that title may contain pending # A problem with the following is that title may contain pending
# references, e.g. :ref:`tag-tips` # references, e.g. :ref:`tag-tips`
@ -157,7 +165,7 @@ def process_posts(app, doctree):
excerpt.append(child.deepcopy()) excerpt.append(child.deepcopy())
else: else:
count = 0 count = 0
for nod in doctree.traverse(nodes.paragraph): for nod in section.traverse(nodes.paragraph):
excerpt.append(nod.deepcopy()) excerpt.append(nod.deepcopy())
count += 1 count += 1
if count >= (node['excerpt'] or 0): if count >= (node['excerpt'] or 0):
@ -165,7 +173,7 @@ def process_posts(app, doctree):
node.replace_self([]) node.replace_self([])
if node['image']: if node['image']:
count = 0 count = 0
for nod in doctree.traverse(nodes.image): for nod in section.traverse(nodes.image):
count += 1 count += 1
if count == node['image']: if count == node['image']:
excerpt.append(nod.deepcopy()) excerpt.append(nod.deepcopy())
@ -189,7 +197,32 @@ def process_posts(app, doctree):
else: else:
update = date update = date
env.ablog_posts[docname] = postinfo = { # if docname ends with `index` use folder name to reference the document
# a potential problem here is that there may be files/folders with the
# same name, so issuing a warning when that's the case may be a good idea
folder, label = os.path.split(docname)
if label == 'index':
folder, label = os.path.split(folder)
if not label:
label = slugify(title)
post_name = docname
section_name = ''
if multi_post and section.parent is not doctree:
section_name = section.attributes['ids'][0]
post_name = docname + '#' + section_name
label += '-' + section_name
# create a reference for the post
app.env.domains['std'].data['labels'][label] = (docname, label, title)
postinfo = {
'docname': docname,
'section': section_name,
'order': order,
'date': date, 'date': date,
'update': update, 'update': update,
'title': title, 'title': title,
@ -202,19 +235,14 @@ def process_posts(app, doctree):
'image': node['image'], 'image': node['image'],
'exclude': node['exclude']} 'exclude': node['exclude']}
# if docname ends with `index` use folder name to reference the document if docname not in env.ablog_posts:
# a potential problem here is that there may be files/folders with the env.ablog_posts[docname] = []
# same name, so issuing a warning when that's the case may be a good idea env.ablog_posts[docname].append(postinfo)
folder, label = os.path.split(docname)
if label == 'index':
folder, label = os.path.split(folder)
app.env.domains['std'].data['labels'][label] = (docname, label, title)
# instantiate catalogs and collections here # instantiate catalogs and collections here
# so that references are created and no warnings are issued # so that references are created and no warnings are issued
blog = Blog(app)
for key in ['tags', 'author', 'category', 'location']: for key in ['tags', 'author', 'category', 'location']:
catalog = blog.catalogs[key] catalog = blog.catalogs[key]
for label in postinfo[key]: for label in postinfo[key]:
@ -346,5 +374,6 @@ def register_posts(app):
"""Register posts found in the Sphinx build environment.""" """Register posts found in the Sphinx build environment."""
blog = Blog() blog = Blog()
for docname, postinfo in getattr(app.env, 'ablog_posts', {}).items(): for docname, posts in getattr(app.env, 'ablog_posts', {}).items():
for postinfo in posts:
blog.register(docname, postinfo) blog.register(docname, postinfo)

View file

@ -28,7 +28,7 @@
</h1> </h1>
{% for post in archive %} {% for post in archive %}
<div class="section"> <div class="section">
<h2><a href="{{ pathto(post.docname) }}">{{ post.title }}</a></h2> <h2><a href="{{ pathto(post.docname) }}{{ anchor(post) }}">{{ post.title }}</a></h2>
<ul class="ablog-archive"> <ul class="ablog-archive">
<li>{% if post.published %} <li>{% if post.published %}

View file

@ -5,7 +5,7 @@
<span style="float: left;"> <span style="float: left;">
{% if post.prev %} {% if post.prev %}
{% if not ablog.fontawesome %}{{ gettext('Previous') }}: {% endif %} {% if not ablog.fontawesome %}{{ gettext('Previous') }}: {% endif %}
<a href="{{ pathto(post.prev.docname) }}"> <a href="{{ pathto(post.prev.docname) }}{{ anchor(post.prev) }}">
{% if ablog.fontawesome %}<i class="fa fa-arrow-circle-left"></i>{% endif %} {% if ablog.fontawesome %}<i class="fa fa-arrow-circle-left"></i>{% endif %}
{{ post.prev.title }} {{ post.prev.title }}
</a> </a>
@ -15,7 +15,7 @@
<span style="float: right;"> <span style="float: right;">
{% if post.next %} {% if post.next %}
{% if not ablog.fontawesome %}{{ gettext('Next') }}: {% endif %} {% if not ablog.fontawesome %}{{ gettext('Next') }}: {% endif %}
<a href="{{ pathto(post.next.docname) }}"> <a href="{{ pathto(post.next.docname) }}{{ anchor(post.next) }}">
{{ post.next.title }} {{ post.next.title }}
{% if ablog.fontawesome %}<i class="fa fa-arrow-circle-right"></i>{% endif %} {% if ablog.fontawesome %}<i class="fa fa-arrow-circle-right"></i>{% endif %}
</a> </a>

View file

@ -3,7 +3,7 @@
<ul> <ul>
{% set pcount = 1 %} {% set pcount = 1 %}
{% for recent in ablog.recent(5, pagename) %} {% for recent in ablog.recent(5, pagename) %}
<li><a href="{{ pathto(recent.docname) }}">{{ recent.title }}</a></li> <li><a href="{{ pathto(recent.docname) }}{{ anchor(recent) }}">{{ recent.title }}</a></li>
{% endfor %} {% endfor %}
</ul> </ul>
{% endif %} {% endif %}