better_figures_and_images.py 2.8 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485
  1. """
  2. Better Figures & Images
  3. ------------------------
  4. This plugin:
  5. - Adds a style="width: ???px; height: auto;" to each image in the content
  6. - Also adds the width of the contained image to any parent div.figures.
  7. - If RESPONSIVE_IMAGES == True, also adds style="max-width: 100%;"
  8. - Corrects alt text: if alt == image filename, set alt = ''
  9. TODO: Need to add a test.py for this plugin.
  10. """
  11. from __future__ import unicode_literals
  12. from os import path, access, R_OK
  13. from pelican import signals
  14. from bs4 import BeautifulSoup
  15. from PIL import Image
  16. import logging
  17. logger = logging.getLogger(__name__)
  18. def content_object_init(instance):
  19. if instance._content is not None:
  20. content = instance._content
  21. soup = BeautifulSoup(content)
  22. if 'img' in content:
  23. for img in soup('img'):
  24. logger.debug('Better Fig. PATH: %s', instance.settings['PATH'])
  25. logger.debug('Better Fig. img.src: %s', img['src'])
  26. img_path, img_filename = path.split(img['src'])
  27. logger.debug('Better Fig. img_path: %s', img_path)
  28. logger.debug('Better Fig. img_fname: %s', img_filename)
  29. # Strip off {filename}, |filename| or /static
  30. if img_path.startswith(('{filename}', '|filename|')):
  31. img_path = img_path[10:]
  32. elif img_path.startswith('/static'):
  33. img_path = img_path[7:]
  34. else:
  35. logger.warning('Better Fig. Error: img_path should start with either {filename}, |filename| or /static')
  36. # Build the source image filename
  37. src = instance.settings['PATH'] + img_path + '/' + img_filename
  38. logger.debug('Better Fig. src: %s', src)
  39. if not (path.isfile(src) and access(src, R_OK)):
  40. logger.error('Better Fig. Error: image not found: %s', src)
  41. # Open the source image and query dimensions; build style string
  42. im = Image.open(src)
  43. extra_style = 'width: {}px; height: auto;'.format(im.size[0])
  44. if 'RESPONSIVE_IMAGES' in instance.settings and instance.settings['RESPONSIVE_IMAGES']:
  45. extra_style += ' max-width: 100%;'
  46. if img.get('style'):
  47. img['style'] += extra_style
  48. else:
  49. img['style'] = extra_style
  50. if img['alt'] == img['src']:
  51. img['alt'] = ''
  52. fig = img.find_parent('div', 'figure')
  53. if fig:
  54. if fig.get('style'):
  55. fig['style'] += extra_style
  56. else:
  57. fig['style'] = extra_style
  58. instance._content = soup.decode()
  59. def register():
  60. signals.content_object_init.connect(content_object_init)