diff --git a/representative_image/Readme.md b/representative_image/Readme.md new file mode 100644 index 0000000..a26c5f2 --- /dev/null +++ b/representative_image/Readme.md @@ -0,0 +1,8 @@ +# Summary + +This plugin extracts a presentative image from the article's summary or article's content. The image can be access at `article.repImage`. + +The plugin also remove any images from the summary after extraction to avoid duplication. + +It allows the flexibility on where and how to display the representative image of an article together with its summary in a template page. For example, the article metadata can be displayed in thumbnail format, in which there is a short summary and an image. The layout of the summary and the image can be varied for aesthetical purpose. It doesn't have to depend on article's content format. + diff --git a/representative_image/__init__.py b/representative_image/__init__.py new file mode 100644 index 0000000..f52720f --- /dev/null +++ b/representative_image/__init__.py @@ -0,0 +1 @@ +from .representative_image import * diff --git a/representative_image/representative_image.py b/representative_image/representative_image.py new file mode 100644 index 0000000..7d5d61c --- /dev/null +++ b/representative_image/representative_image.py @@ -0,0 +1,31 @@ +from pelican import signals +from pelican.contents import Content, Article +from bs4 import BeautifulSoup + +def images_extraction(instance): + representativeImage = None + if type(instance) == Article: + # Process Summary: + # If summary contains images, extract one to be the representativeImage and remove images from summary + soup = BeautifulSoup(instance.summary, 'html.parser') + images = soup.find_all('img') + for i in images: + if not representativeImage: + representativeImage = i['src'] + i.extract() + if len(images) > 0: + # set _summary field which is based on metadata. summary field is only based on article's content and not settable + instance._summary = unicode(soup) + + # If there are no image in summary, look for it in the content body + if not representativeImage: + soup = BeautifulSoup(instance.content, 'html.parser') + imageTag = soup.find('img') + if imageTag: + representativeImage = imageTag['src'] + + # Set the attribute to content instance + instance.repImage = representativeImage + +def register(): + signals.content_object_init.connect(images_extraction) diff --git a/representative_image/test_representative_image.py b/representative_image/test_representative_image.py new file mode 100644 index 0000000..60efa8b --- /dev/null +++ b/representative_image/test_representative_image.py @@ -0,0 +1,54 @@ +#!/bin/sh +import unittest + +from jinja2.utils import generate_lorem_ipsum + +# Generate content with image +TEST_CONTENT_IMAGE_URL = 'https://testimage.com/test.jpg' +TEST_CONTENT = str(generate_lorem_ipsum(n=3, html=True)) + ''+ str(generate_lorem_ipsum(n=2,html=True)) +TEST_SUMMARY_IMAGE_URL = 'https://testimage.com/summary.jpg' +TEST_SUMMARY_WITHOUTIMAGE = str(generate_lorem_ipsum(n=1, html=True)) +TEST_SUMMARY_WITHIMAGE = TEST_SUMMARY_WITHOUTIMAGE + '' + + +from pelican.contents import Article +import representative_image + +class TestRepresentativeImage(unittest.TestCase): + + def setUp(self): + super(TestRepresentativeImage, self).setUp() + representative_image.register() + + def test_extract_image_from_content(self): + args = { + 'content': TEST_CONTENT, + 'metadata': { + 'summary': TEST_SUMMARY_WITHOUTIMAGE, + }, + } + + article = Article(**args) + self.assertEqual(article.repImage, TEST_CONTENT_IMAGE_URL) + + def test_extract_image_from_summary(self): + args = { + 'content': TEST_CONTENT, + 'metadata': { + 'summary': TEST_SUMMARY_WITHIMAGE, + }, + } + + article = Article(**args) + self.assertEqual(article.repImage, TEST_SUMMARY_IMAGE_URL) + self.assertEqual(article.summary, TEST_SUMMARY_WITHOUTIMAGE) + +if __name__ == '__main__': + unittest.main() + + + + + + +