diff --git a/docs/image_information.rst b/docs/image_information.rst new file mode 100644 index 0000000..529b46c --- /dev/null +++ b/docs/image_information.rst @@ -0,0 +1,29 @@ +=================== + Image information +=================== + +Additional information on an image can be given in a file using the `markdown`_ +syntax, named ``.md`` (example: ``IMG_5206.md``):: + + Title: My awesome photo + + And a description with *Markdown* syntax. + +EXIF data is directly extracted, see :ref:`simple-exif-data`. Some meta-data +keys are used by Sigal to get the useful informations on the gallery: + +- *Title*: the image title. + +Any additional meta-data is available in the templates. For instance:: + + Location: Las Vegas + +can be used in the template with: + +.. code-block:: jinja + + {% if media.meta.location %} +

Location: {{ media.meta.location[0] }} + {% endif %} + +.. _markdown: http://daringfireball.net/projects/markdown/ diff --git a/docs/index.rst b/docs/index.rst index 75585ad..15620ce 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -10,6 +10,7 @@ Documentation getting_started configuration album_information + image_information themes plugins changelog diff --git a/sigal/gallery.py b/sigal/gallery.py index f49e064..ba28c58 100644 --- a/sigal/gallery.py +++ b/sigal/gallery.py @@ -23,10 +23,8 @@ from __future__ import absolute_import, print_function -import codecs import fnmatch import logging -import markdown import multiprocessing import os import sys @@ -42,7 +40,7 @@ from .compat import UnicodeMixin, strxfrm, url_quote from .image import process_image, get_exif_tags from .log import colored, BLUE from .settings import get_thumb -from .utils import copy, check_or_create_dir, url_from_path +from .utils import copy, check_or_create_dir, url_from_path, read_markdown from .video import process_video from .writer import Writer @@ -80,6 +78,7 @@ class Media(UnicodeMixin): self.raw_exif = None self.exif = None self.date = None + self._get_metadata() signals.media_initialized.send(self) def __repr__(self): @@ -119,6 +118,18 @@ class Media(UnicodeMixin): return return url_from_path(self.thumb_name) + def _get_metadata(self): + """ Get image metadata from filename.md: title, description, meta.""" + self.description = '' + self.meta = {} + self.title = '' + + descfile = splitext(self.src_path)[0] + '.md' + if isfile(descfile): + meta = read_markdown(descfile) + for key, val in meta.items(): + setattr(self, key, val) + class Image(Media): """Gather all informations on an image file.""" @@ -246,24 +257,16 @@ class Album(UnicodeMixin): """ descfile = join(self.src_path, self.description_file) + self.description = '' + self.meta = {} + # default: get title from directory name + self.title = os.path.basename(self.path if self.path != '.' + else self.src_path) if isfile(descfile): - # Use utf-8-sig codec to remove BOM if it is present - with codecs.open(descfile, 'r', 'utf-8-sig') as f: - text = f.read() - - md = markdown.Markdown(extensions=['meta']) - html = md.convert(text) - - self.title = md.Meta.get('title', [''])[0] - self.description = html - self.meta = md.Meta.copy() - else: - self.description = '' - self.meta = {} - # default: get title from directory name - self.title = os.path.basename(self.path if self.path != '.' - else self.src_path) + meta = read_markdown(descfile) + for key, val in meta.items(): + setattr(self, key, val) def create_output_directories(self): """Create output directories for thumbnails and original images.""" diff --git a/sigal/themes/colorbox/templates/index.html b/sigal/themes/colorbox/templates/index.html index a481c60..6b66965 100644 --- a/sigal/themes/colorbox/templates/index.html +++ b/sigal/themes/colorbox/templates/index.html @@ -90,7 +90,7 @@ {% if loop.index % nb_columns == 0 %}omega{% endif%}"> {{ media.filename }} + title="{{ media.title if media.title else media.filename }}" /> {% endif %} {% if media.type == "video" %} @@ -101,7 +101,7 @@ class="gallery" inline='yes' title="{{ media.filename }}" {% if media.big %} data-big="{{ media.big }}"{% endif %}> {{ media.filename }} + title="{{ media.title if media.title else media.filename }}" />

diff --git a/sigal/themes/galleria/templates/index.html b/sigal/themes/galleria/templates/index.html index f6907f4..4bda703 100644 --- a/sigal/themes/galleria/templates/index.html +++ b/sigal/themes/galleria/templates/index.html @@ -60,6 +60,8 @@ {% if album.medias %} {% macro img_description(media) -%} {%- if media.big %}Full size{% endif %} + {% if media.description %}
{{ media.description }}{% endif %} + {%- if media.exif %}
{% if media.exif.iso %}ISO: {{ media.exif.iso }}, {% endif %} @@ -76,16 +78,18 @@ {% if media.type == "image" %} {{ media.filename }} {% endif %} {% if media.type == "video" %} {{ media.filename }} + data-title="{{ media.title if media.title else media.filename }}" + data-description="{{ img_description(media) }}" + data-layer="" /> {% endif %} {% endfor %} diff --git a/sigal/utils.py b/sigal/utils.py index 9bdedce..1ee3255 100644 --- a/sigal/utils.py +++ b/sigal/utils.py @@ -20,6 +20,8 @@ # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS # IN THE SOFTWARE. +import codecs +import markdown import os import shutil @@ -46,3 +48,18 @@ def url_from_path(path): return path else: return '/'.join(path.split(os.sep)) + + +def read_markdown(filename): + # Use utf-8-sig codec to remove BOM if it is present + with codecs.open(filename, 'r', 'utf-8-sig') as f: + text = f.read() + + md = markdown.Markdown(extensions=['meta']) + html = md.convert(text) + + return { + 'title': md.Meta.get('title', [''])[0], + 'description': html, + 'meta': md.Meta.copy() + } diff --git a/tests/sample/pictures/dir1/test1/11.md b/tests/sample/pictures/dir1/test1/11.md new file mode 100644 index 0000000..84c272b --- /dev/null +++ b/tests/sample/pictures/dir1/test1/11.md @@ -0,0 +1,4 @@ +Title: Foo Bar +Location: Bavaria + +This is a funny description of this image diff --git a/tests/test_gallery.py b/tests/test_gallery.py index d9e60f2..71d3df7 100644 --- a/tests/test_gallery.py +++ b/tests/test_gallery.py @@ -71,6 +71,8 @@ def test_media(settings): assert m.dst_path == join(settings['destination'], file_path) assert m.thumb_name == thumb assert m.thumb_path == join(settings['destination'], path, thumb) + assert m.title == "Foo Bar" + assert m.description == "

This is a funny description of this image

" assert repr(m) == "('{}')".format(file_path) assert str(m) == file_path diff --git a/tests/test_utils.py b/tests/test_utils.py index 08e7e26..3d0227f 100644 --- a/tests/test_utils.py +++ b/tests/test_utils.py @@ -1,7 +1,7 @@ # -*- coding: utf-8 -*- import os -from sigal.utils import copy, check_or_create_dir, url_from_path +from sigal import utils CURRENT_DIR = os.path.dirname(__file__) SAMPLE_DIR = os.path.join(CURRENT_DIR, 'sample') @@ -11,28 +11,37 @@ def test_copy(tmpdir): filename = 'exo20101028-b-full.jpg' src = os.path.join(SAMPLE_DIR, 'pictures', 'dir2', filename) dst = str(tmpdir.join(filename)) - copy(src, dst) + utils.copy(src, dst) assert os.path.isfile(dst) filename = 'm57_the_ring_nebula-587px.jpg' src = os.path.join(SAMPLE_DIR, 'pictures', 'dir2', filename) dst = str(tmpdir.join(filename)) - copy(src, dst, symlink=True) + utils.copy(src, dst, symlink=True) assert os.path.islink(dst) assert os.readlink(dst) == src filename = 'exo20101028-b-full.jpg' src = os.path.join(SAMPLE_DIR, 'pictures', 'dir2', filename) - copy(src, dst, symlink=True) + utils.copy(src, dst, symlink=True) assert os.path.islink(dst) assert os.readlink(dst) == src def test_check_or_create_dir(tmpdir): path = str(tmpdir.join('new_directory')) - check_or_create_dir(path) + utils.check_or_create_dir(path) assert os.path.isdir(path) def test_url_from_path(): - assert url_from_path(os.sep.join(['foo', 'bar'])) == 'foo/bar' + assert utils.url_from_path(os.sep.join(['foo', 'bar'])) == 'foo/bar' + + +def test_read_markdown(): + src = os.path.join(SAMPLE_DIR, 'pictures', 'dir1', 'test1', '11.md') + m = utils.read_markdown(src) + assert m['title'] == "Foo Bar" + assert m['meta']['location'][0] == "Bavaria" + assert m['description'] == \ + "

This is a funny description of this image

"