Browse Source

Image sizer plugin: add image dimensions in HTML code

This plugin adds `width` and `height` tags to `img` when they are not
present. It also adds them when only one of them is present
(respecting proportions).
main
Vincent Bernat 13 years ago
parent
commit
fb968685a9
2 changed files with 170 additions and 0 deletions
  1. +86
    -0
      hyde/ext/plugins/images.py
  2. +84
    -0
      hyde/tests/ext/test_images.py

+ 86
- 0
hyde/ext/plugins/images.py View File

@@ -0,0 +1,86 @@
# -*- coding: utf-8 -*-
"""
Contains classes to handle images related things
"""

from hyde.plugin import Plugin

import re
import Image
from BeautifulSoup import BeautifulSoup

class ImageSizerPlugin(Plugin):
"""
Each HTML page is modified to add width and height for images if
they are not already specified.
"""

def __init__(self, site):
super(ImageSizerPlugin, self).__init__(site)
self.cache = {}

def text_resource_complete(self, resource, text):
"""
When the resource is generated, search for img tag and specify
their sizes.
"""
try:
mode = self.site.config.mode
except AttributeError:
mode = "production"

if not resource.source_file.kind == 'html':
return

if mode.startswith('dev'):
self.logger.debug("Skipping sizer in development mode.")
return

soup = BeautifulSoup(text)
for img in soup.findAll('img'):
if img.has_key('width') and img.has_key('height'):
continue
if not img.has_key('src'):
self.logger.warn("[%s] has an img tag without src attribute" % resource)
continue
if not img['src'] in self.cache:
if not re.match(r"(/[^/]|[^/]).*", img['src']):
# Not a local link
continue
if img['src'].startswith("/"):
# Absolute resource
path = img['src'].lstrip("/")
image = self.site.content.resource_from_relative_deploy_path(path)
else:
# Relative resource
path = resource.node.source_folder.child(img['src'])
image = self.site.content.resource_from_path(path)
if image is None:
self.logger.warn(
"[%s] has an unknown image" % resource)
continue
if image.source_file.kind not in ['png', 'jpg', 'jpeg', 'gif']:
self.logger.warn(
"[%s] has an img tag not linking to an image" % resource)
continue
# Now, get the size of the image
try:
self.cache[img['src']] = Image.open(image.path).size
except IOError:
self.logger.warn(
"Unable to process image [%s]" % image)
self.cache[img['src']] = (None, None)
continue
self.logger.debug("Image [%s] is %s" % (img['src'],
self.cache[img['src']]))
width, height = self.cache[img['src']]
if width is None:
continue
if img.has_key('width'):
height = int(img['width'])*height/width
width = int(img['width'])
elif img.has_key('height'):
width = int(img['height'])*width/height
height = int(img['height'])
img['height'], img['width'] = height, width
return unicode(soup)

+ 84
- 0
hyde/tests/ext/test_images.py View File

@@ -0,0 +1,84 @@
# -*- coding: utf-8 -*-
"""
Use nose
`$ pip install nose`
`$ nosetests`
"""
from hyde.fs import File, Folder
from hyde.generator import Generator
from hyde.site import Site

from pyquery import PyQuery

TEST_SITE = File(__file__).parent.parent.child_folder('_test')
IMAGE_SOURCE = File(__file__).parent.child_folder('optipng')
IMAGE_NAME = "hyde-lt-b.png"
IMAGE_SIZE = (538, 132)

class TestImageSizer(object):

def setUp(self):
TEST_SITE.make()
TEST_SITE.parent.child_folder(
'sites/test_jinja').copy_contents_to(TEST_SITE)
IMAGES = TEST_SITE.child_folder('content/media/img')
IMAGES.make()
IMAGE_SOURCE.copy_contents_to(IMAGES)

def tearDown(self):
TEST_SITE.delete()

def _generic_test_image(self, text):
site = Site(TEST_SITE)
site.config.mode = "production"
site.config.plugins = ['hyde.ext.plugins.images.ImageSizerPlugin']
tlink = File(site.content.source_folder.child('timg.html'))
tlink.write(text)
gen = Generator(site)
gen.generate_all()
f = File(site.config.deploy_root_path.child(tlink.name))
assert f.exists
html = f.read_all()
assert html
print html
return html

def test_size_image(self):
text = u"""
<img src="/media/img/%s">
""" % IMAGE_NAME
html = self._generic_test_image(text)
assert ' width="%d"' % IMAGE_SIZE[0] in html
assert ' height="%d"' % IMAGE_SIZE[1] in html

def test_size_image_relative(self):
text = u"""
<img src="media/img/%s">
""" % IMAGE_NAME
html = self._generic_test_image(text)
assert ' width="%d"' % IMAGE_SIZE[0] in html
assert ' height="%d"' % IMAGE_SIZE[1] in html

def test_size_image_no_resize(self):
text = u"""
<img src="/media/img/%s" width="2000" height="150">
""" % IMAGE_NAME
html = self._generic_test_image(text)
assert ' width="%d"' % IMAGE_SIZE[0] not in html
assert ' height="%d"' % IMAGE_SIZE[1] not in html

def test_size_image_size_proportional(self):
text = u"""
<img src="/media/img/%s" width="%d">
""" % (IMAGE_NAME, IMAGE_SIZE[0]*2)
html = self._generic_test_image(text)
assert ' width="%d"' % (IMAGE_SIZE[0]*2) in html
assert ' height="%d"' % (IMAGE_SIZE[1]*2) in html

def test_size_image_not_exists(self):
text = u"""
<img src="/media/img/hyde-logo-no.png">
"""
html = self._generic_test_image(text)



Loading…
Cancel
Save