read_more_link.py 2.8 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586
  1. # -*- coding: utf-8 -*-
  2. """
  3. Read More Link
  4. ===========================
  5. This plugin inserts an inline "read more" or "continue" link into the last html element of the object summary.
  6. For more information, please visit: http://vuongnguyen.com/creating-inline-read-more-link-python-pelican-lxml.html
  7. """
  8. from pelican import signals, contents
  9. from pelican.utils import truncate_html_words
  10. from pelican.generators import ArticlesGenerator
  11. try:
  12. from lxml.html import fragment_fromstring, fragments_fromstring, tostring
  13. from lxml.etree import ParserError
  14. except ImportError:
  15. raise Exception("Unable to find lxml. To use READ_MORE_LINK, you need lxml")
  16. def insert_into_last_element(html, element):
  17. """
  18. function to insert an html element into another html fragment
  19. example:
  20. html = '<p>paragraph1</p><p>paragraph2...</p>'
  21. element = '<a href="/read-more/">read more</a>'
  22. ---> '<p>paragraph1</p><p>paragraph2...<a href="/read-more/">read more</a></p>'
  23. """
  24. try:
  25. item = fragment_fromstring(element)
  26. except (ParserError, TypeError) as e:
  27. item = fragment_fromstring('<span></span>')
  28. try:
  29. doc = fragments_fromstring(html)
  30. doc[-1].append(item)
  31. return ''.join(tostring(e) for e in doc)
  32. except (ParserError, TypeError) as e:
  33. return ''
  34. def insert_read_more_link(instance):
  35. """
  36. Insert an inline "read more" link into the last element of the summary
  37. :param instance:
  38. :return:
  39. """
  40. # only deals with Article type
  41. if type(instance) != contents.Article: return
  42. SUMMARY_MAX_LENGTH = instance.settings.get('SUMMARY_MAX_LENGTH')
  43. READ_MORE_LINK = instance.settings.get('READ_MORE_LINK', None)
  44. READ_MORE_LINK_FORMAT = instance.settings.get('READ_MORE_LINK_FORMAT',
  45. '<a class="read-more" href="/{url}">{text}</a>')
  46. if not (SUMMARY_MAX_LENGTH and READ_MORE_LINK and READ_MORE_LINK_FORMAT): return
  47. if hasattr(instance, '_summary') and instance._summary:
  48. summary = instance._summary
  49. else:
  50. summary = truncate_html_words(instance.content, SUMMARY_MAX_LENGTH)
  51. if summary != instance.content:
  52. read_more_link = READ_MORE_LINK_FORMAT.format(url=instance.url, text=READ_MORE_LINK)
  53. instance._summary = insert_into_last_element(summary, read_more_link)
  54. def run_plugin(generators):
  55. for generator in generators:
  56. if isinstance(generator, ArticlesGenerator):
  57. for article in generator.articles:
  58. insert_read_more_link(article)
  59. def register():
  60. try:
  61. signals.all_generators_finalized.connect(run_plugin)
  62. except AttributeError:
  63. # NOTE: This may result in #314 so shouldn't really be relied on
  64. # https://github.com/getpelican/pelican-plugins/issues/314
  65. signals.content_object_init.connect(insert_read_more_link)