Browse Source

summary plugin added

master
mb@mb 7 years ago
parent
commit
baffbbbab9
  1. 56
      plugins/summary/Readme.rst
  2. 1
      plugins/summary/__init__.py
  3. 105
      plugins/summary/summary.py
  4. 96
      plugins/summary/test_summary.py

56
plugins/summary/Readme.rst

@ -0,0 +1,56 @@
Summary
-------
This plugin allows easy, variable length summaries directly embedded into the
body of your articles. It introduces two new settings: ``SUMMARY_BEGIN_MARKER``
and ``SUMMARY_END_MARKER``: strings which can be placed directly into an article
to mark the beginning and end of a summary. When found, the standard
``SUMMARY_MAX_LENGTH`` setting will be ignored. The markers themselves will also
be removed from your articles before they are published. The default values
are ``<!-- PELICAN_BEGIN_SUMMARY -->`` and ``<!-- PELICAN_END_SUMMARY -->``.
For example::
Title: My super title
Date: 2010-12-03 10:20
Tags: thats, awesome
Category: yeah
Slug: my-super-post
Author: Alexis Metaireau
This is the content of my super blog post.
<!-- PELICAN_END_SUMMARY -->
and this content occurs after the summary.
Here, the summary is taken to be the first line of the post. Because no
beginning marker was found, it starts at the top of the body. It is possible
to leave out the end marker instead, in which case the summary will start at the
beginning marker and continue to the end of the body.
If no beginning or end marker is found, and if ``SUMMARY_USE_FIRST_PARAGRAPH``
is enabled in the settings, the summary will be the first paragraph of the post.
The plugin also sets a ``has_summary`` attribute on every article. It is True
for articles with an explicitly-defined summary, and False otherwise. (It is
also False for an article truncated by ``SUMMARY_MAX_LENGTH``.) Your templates
can use this e.g. to add a link to the full text at the end of the summary.
reST example
~~~~~~~~~~~~
Inserting the markers into a reStructuredText document makes use of the
comment directive, because raw HTML is automatically escaped. The reST equivalent of the above Markdown example looks like this::
My super title
##############
:date: 2010-12-03 10:20
:tags: thats, awesome
:category: yeah
:slug: my-super-post
:author: Alexis Metaireau
This is the content of my super blog post.
.. PELICAN_END_SUMMARY
and this content occurs after the summary.

1
plugins/summary/__init__.py

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

105
plugins/summary/summary.py

@ -0,0 +1,105 @@
"""
Summary
-------
This plugin allows easy, variable length summaries directly embedded into the
body of your articles.
"""
from __future__ import unicode_literals
from pelican import signals
from pelican.generators import ArticlesGenerator, StaticGenerator, PagesGenerator
import re
def initialized(pelican):
from pelican.settings import DEFAULT_CONFIG
DEFAULT_CONFIG.setdefault('SUMMARY_BEGIN_MARKER',
'<!-- PELICAN_BEGIN_SUMMARY -->')
DEFAULT_CONFIG.setdefault('SUMMARY_END_MARKER',
'<!-- PELICAN_END_SUMMARY -->')
DEFAULT_CONFIG.setdefault('SUMMARY_USE_FIRST_PARAGRAPH', False)
if pelican:
pelican.settings.setdefault('SUMMARY_BEGIN_MARKER',
'<!-- PELICAN_BEGIN_SUMMARY -->')
pelican.settings.setdefault('SUMMARY_END_MARKER',
'<!-- PELICAN_END_SUMMARY -->')
pelican.settings.setdefault('SUMMARY_USE_FIRST_PARAGRAPH', False)
def extract_summary(instance):
# if summary is already specified, use it
# if there is no content, there's nothing to do
if hasattr(instance, '_summary'):
instance.has_summary = True
return
if not instance._content:
instance.has_summary = False
return
begin_marker = instance.settings['SUMMARY_BEGIN_MARKER']
end_marker = instance.settings['SUMMARY_END_MARKER']
use_first_paragraph = instance.settings['SUMMARY_USE_FIRST_PARAGRAPH']
remove_markers = True
content = instance._content
begin_summary = -1
end_summary = -1
if begin_marker:
begin_summary = content.find(begin_marker)
if end_marker:
end_summary = content.find(end_marker)
if begin_summary == -1 and end_summary == -1 and use_first_paragraph:
begin_marker, end_marker = '<p>', '</p>'
remove_markers = False
begin_summary = content.find(begin_marker)
end_summary = content.find(end_marker)
if begin_summary == -1 and end_summary == -1:
instance.has_summary = False
return
# skip over the begin marker, if present
if begin_summary == -1:
begin_summary = 0
else:
begin_summary = begin_summary + len(begin_marker)
if end_summary == -1:
end_summary = None
summary = content[begin_summary:end_summary]
if remove_markers:
# remove the markers from the content
if begin_summary:
content = content.replace(begin_marker, '', 1)
if end_summary:
content = content.replace(end_marker, '', 1)
summary = re.sub(r"<div.*>", "", summary)
summary = re.sub(r"</div>", "", summary)
instance._content = content
instance._summary = summary
instance.has_summary = True
def run_plugin(generators):
for generator in generators:
if isinstance(generator, ArticlesGenerator):
for article in generator.articles:
extract_summary(article)
elif isinstance(generator, PagesGenerator):
for page in generator.pages:
extract_summary(page)
def register():
signals.initialized.connect(initialized)
try:
signals.all_generators_finalized.connect(run_plugin)
except AttributeError:
# NOTE: This results in #314 so shouldn't really be relied on
# https://github.com/getpelican/pelican-plugins/issues/314
signals.content_object_init.connect(extract_summary)

96
plugins/summary/test_summary.py

@ -0,0 +1,96 @@
# -*- coding: utf-8 -*-
import unittest
from jinja2.utils import generate_lorem_ipsum
# generate one paragraph, enclosed with <p>
TEST_CONTENT = str(generate_lorem_ipsum(n=1))
TEST_SUMMARY = generate_lorem_ipsum(n=1, html=False)
from pelican.contents import Page
import pelican.settings
import summary
class TestSummary(unittest.TestCase):
def setUp(self):
super(TestSummary, self).setUp()
pelican.settings.DEFAULT_CONFIG['SUMMARY_MAX_LENGTH'] = None
pelican.settings.DEFAULT_CONFIG['SUMMARY_USE_FIRST_PARAGRAPH'] = False
summary.register()
summary.initialized(None)
self.page_kwargs = {
'content': TEST_CONTENT,
'context': {
'localsiteurl': '',
},
'metadata': {
'summary': TEST_SUMMARY,
'title': 'foo bar',
'author': 'Blogger',
},
}
def _copy_page_kwargs(self):
# make a deep copy of page_kwargs
page_kwargs = dict([(key, self.page_kwargs[key]) for key in
self.page_kwargs])
for key in page_kwargs:
if not isinstance(page_kwargs[key], dict):
break
page_kwargs[key] = dict([(subkey, page_kwargs[key][subkey])
for subkey in page_kwargs[key]])
return page_kwargs
def test_end_summary(self):
page_kwargs = self._copy_page_kwargs()
del page_kwargs['metadata']['summary']
page_kwargs['content'] = (
TEST_SUMMARY + '<!-- PELICAN_END_SUMMARY -->' + TEST_CONTENT)
page = Page(**page_kwargs)
summary.extract_summary(page)
# test both the summary and the marker removal
self.assertEqual(page.summary, TEST_SUMMARY)
self.assertEqual(page.content, TEST_SUMMARY + TEST_CONTENT)
def test_begin_summary(self):
page_kwargs = self._copy_page_kwargs()
del page_kwargs['metadata']['summary']
page_kwargs['content'] = (
'FOOBAR<!-- PELICAN_BEGIN_SUMMARY -->' + TEST_CONTENT)
page = Page(**page_kwargs)
summary.extract_summary(page)
# test both the summary and the marker removal
self.assertEqual(page.summary, TEST_CONTENT)
self.assertEqual(page.content, 'FOOBAR' + TEST_CONTENT)
def test_begin_end_summary(self):
page_kwargs = self._copy_page_kwargs()
del page_kwargs['metadata']['summary']
page_kwargs['content'] = (
'FOOBAR<!-- PELICAN_BEGIN_SUMMARY -->' + TEST_SUMMARY +
'<!-- PELICAN_END_SUMMARY -->' + TEST_CONTENT)
page = Page(**page_kwargs)
summary.extract_summary(page)
# test both the summary and the marker removal
self.assertEqual(page.summary, TEST_SUMMARY)
self.assertEqual(page.content, 'FOOBAR' + TEST_SUMMARY + TEST_CONTENT)
def test_use_first_paragraph(self):
page_kwargs = self._copy_page_kwargs()
del page_kwargs['metadata']['summary']
pelican.settings.DEFAULT_CONFIG['SUMMARY_USE_FIRST_PARAGRAPH'] = True
page_kwargs['content'] = '<p>' + TEST_SUMMARY + '</p>' + TEST_CONTENT
page = Page(**page_kwargs)
summary.extract_summary(page)
# test both the summary and the marker removal
self.assertEqual(page.summary, TEST_SUMMARY)
self.assertEqual(page.content, '<p>' + TEST_SUMMARY + '</p>' + TEST_CONTENT)
if __name__ == '__main__':
unittest.main()
Loading…
Cancel
Save