Browse Source

Merge pull request #308 from mclate/master

Liquid tag for inline images (base64 data uri)
Justin Mayer 10 years ago
parent
commit
28cdc8c09a
2 changed files with 98 additions and 0 deletions
  1. 11 0
      liquid_tags/Readme.md
  2. 87 0
      liquid_tags/b64img.py

+ 11 - 0
liquid_tags/Readme.md

@@ -25,6 +25,17 @@ To insert a sized and labeled image in your document, enable the
 
     {% img [class name(s)] path/to/image [width [height]] [title text | "title text" ["alt text"]] %}
 
+### Base64 Image (inline image) tag
+
+There is one more tag for image: ``b64img``. It is based on ``img`` tag, but instead of inserting link on image it acutally reads image and inserts it as base64 text into ``<img src=`` attribute.
+
+To use it:
+
+1. Enable ``liquid_tags.b64img``
+1. Insert tag as you'd insert image one: ``{% b64img [class name(s)] path/to/image [width [height]] [title text | "title text" ["alt text"]] %}``
+
+Images are read on compilation phase so you can use any local path (just be sure that image will remain there on next compilation)
+
 ## Youtube Tag
 To insert youtube video into a post, enable the
 ``liquid_tags.youtube`` plugin, and add to your document:

+ 87 - 0
liquid_tags/b64img.py

@@ -0,0 +1,87 @@
+"""
+Image Tag
+---------
+This implements a Liquid-style image tag for Pelican,
+based on the liquid img tag which is based on the octopress image tag [1]_
+
+Syntax
+------
+{% b64img [class name(s)] [http[s]:/]/path/to/image [width [height]] [title text | "title text" ["alt text"]] %}
+
+Examples
+--------
+{% b64img /images/ninja.png Ninja Attack! %}
+{% b64img left half http://site.com/images/ninja.png Ninja Attack! %}
+{% b64img left half http://site.com/images/ninja.png 150 150 "Ninja Attack!" "Ninja in attack posture" %}
+
+Output
+------
+<img src="data:;base64,....">
+<img class="left half" src="data:;base64,..." title="Ninja Attack!" alt="Ninja Attack!">
+<img class="left half" src="data:;base64,..." width="150" height="150" title="Ninja Attack!" alt="Ninja in attack posture">
+
+[1] https://github.com/imathis/octopress/blob/master/plugins/image_tag.rb
+"""
+import re
+import base64
+import urllib2
+from .mdx_liquid_tags import LiquidTags
+
+SYNTAX = '{% b64img [class name(s)] [http[s]:/]/path/to/image [width [height]] [title text | "title text" ["alt text"]] %}'
+
+# Regular expression to match the entire syntax
+ReImg = re.compile("""(?P<class>\S.*\s+)?(?P<src>(?:https?:\/\/|\/|\S+\/)\S+)(?:\s+(?P<width>\d+))?(?:\s+(?P<height>\d+))?(?P<title>\s+.+)?""")
+
+# Regular expression to split the title and alt text
+ReTitleAlt = re.compile("""(?:"|')(?P<title>[^"']+)?(?:"|')\s+(?:"|')(?P<alt>[^"']+)?(?:"|')""")
+
+
+def _get_file(src):
+    """ Return content from local or remote file. """
+    try:
+        if '://' in src or src[0:2] == '//':  # Most likely this is remote file
+            response = urllib2.urlopen(src)
+            return response.read()
+        else:
+            with open(src, 'rb') as fh:
+                return fh.read()
+    except Exception, e:
+        raise RuntimeError('Error generating base64image: {}'.format(e))
+
+
+def base64image(src):
+    """ Generate base64 encoded image from srouce file. """
+    return base64.b64encode(_get_file(src))
+
+
+@LiquidTags.register('b64img')
+def b64img(preprocessor, tag, markup):
+    attrs = None
+
+    # Parse the markup string
+    match = ReImg.search(markup)
+    if match:
+        attrs = dict([(key, val.strip())
+                      for (key, val) in match.groupdict().iteritems() if val])
+    else:
+        raise ValueError('Error processing input. '
+                         'Expected syntax: {0}'.format(SYNTAX))
+
+    # Check if alt text is present -- if so, split it from title
+    if 'title' in attrs:
+        match = ReTitleAlt.search(attrs['title'])
+        if match:
+            attrs.update(match.groupdict())
+        if not attrs.get('alt'):
+            attrs['alt'] = attrs['title']
+
+    attrs['src'] = 'data:;base64,{}'.format(base64image(attrs['src']))
+
+    # Return the formatted text
+    return "<img {0}>".format(' '.join('{0}="{1}"'.format(key, val)
+                                       for (key, val) in attrs.iteritems()))
+
+
+#----------------------------------------------------------------------
+# This import allows image tag to be a Pelican plugin
+from liquid_tags import register