b64img.py 3.1 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192
  1. """
  2. Image Tag
  3. ---------
  4. This implements a Liquid-style image tag for Pelican,
  5. based on the liquid img tag which is based on the octopress image tag [1]_
  6. Syntax
  7. ------
  8. {% b64img [class name(s)] [http[s]:/]/path/to/image [width [height]] [title text | "title text" ["alt text"]] %}
  9. Examples
  10. --------
  11. {% b64img /images/ninja.png Ninja Attack! %}
  12. {% b64img left half http://site.com/images/ninja.png Ninja Attack! %}
  13. {% b64img left half http://site.com/images/ninja.png 150 150 "Ninja Attack!" "Ninja in attack posture" %}
  14. Output
  15. ------
  16. <img src="data:;base64,....">
  17. <img class="left half" src="data:;base64,..." title="Ninja Attack!" alt="Ninja Attack!">
  18. <img class="left half" src="data:;base64,..." width="150" height="150" title="Ninja Attack!" alt="Ninja in attack posture">
  19. [1] https://github.com/imathis/octopress/blob/master/plugins/image_tag.rb
  20. """
  21. import re
  22. import base64
  23. try:
  24. import urllib.request as urllib2
  25. except ImportError:
  26. import urllib2
  27. from .mdx_liquid_tags import LiquidTags
  28. import six
  29. SYNTAX = '{% b64img [class name(s)] [http[s]:/]/path/to/image [width [height]] [title text | "title text" ["alt text"]] %}'
  30. # Regular expression to match the entire syntax
  31. ReImg = re.compile("""(?P<class>\S.*\s+)?(?P<src>(?:https?:\/\/|\/|\S+\/)\S+)(?:\s+(?P<width>\d+))?(?:\s+(?P<height>\d+))?(?P<title>\s+.+)?""")
  32. # Regular expression to split the title and alt text
  33. ReTitleAlt = re.compile("""(?:"|')(?P<title>[^"']+)?(?:"|')\s+(?:"|')(?P<alt>[^"']+)?(?:"|')""")
  34. def _get_file(src):
  35. """ Return content from local or remote file. """
  36. try:
  37. if '://' in src or src[0:2] == '//': # Most likely this is remote file
  38. response = urllib2.urlopen(src)
  39. return response.read()
  40. else:
  41. with open(src, 'rb') as fh:
  42. return fh.read()
  43. except Exception as e:
  44. raise RuntimeError('Error generating base64image: {}'.format(e))
  45. def base64image(src):
  46. """ Generate base64 encoded image from srouce file. """
  47. return base64.b64encode(_get_file(src))
  48. @LiquidTags.register('b64img')
  49. def b64img(preprocessor, tag, markup):
  50. attrs = None
  51. # Parse the markup string
  52. match = ReImg.search(markup)
  53. if match:
  54. attrs = dict([(key, val.strip())
  55. for (key, val) in six.iteritems(match.groupdict()) if val])
  56. else:
  57. raise ValueError('Error processing input. '
  58. 'Expected syntax: {0}'.format(SYNTAX))
  59. # Check if alt text is present -- if so, split it from title
  60. if 'title' in attrs:
  61. match = ReTitleAlt.search(attrs['title'])
  62. if match:
  63. attrs.update(match.groupdict())
  64. if not attrs.get('alt'):
  65. attrs['alt'] = attrs['title']
  66. attrs['src'] = 'data:;base64,{}'.format(base64image(attrs['src']))
  67. # Return the formatted text
  68. return "<img {0}>".format(' '.join('{0}="{1}"'.format(key, val)
  69. for (key, val) in six.iteritems(attrs)))
  70. #----------------------------------------------------------------------
  71. # This import allows image tag to be a Pelican plugin
  72. from .liquid_tags import register