-
Notifications
You must be signed in to change notification settings - Fork 460
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Support for captioned and ordered images in galleries #3017 #3018
Conversation
nikola/plugins/task/galleries.py
Outdated
Example: | ||
header.jpg This is the header image for my blog |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This format won’t cut it. Filenames could contain spaces. Instead of a custom parser, use something like JSON or YAML.
For galleries: this change provides support for per-image captions and for specifying an order to display images in. We look for a file called metadata.yml in the gallery directory. If this file exists, we read 'name', 'caption' and 'order' from it and apply that metadata when generating the gallery. An entry must have at least 'name' to be considered valid. We cannot guarantee that yaml.safe_load_all() will return the elements in the same order that they are listed in the file.
For galleries: this change provides support for per-image captions and for specifying an order to display images in. We look for a file called metadata.yml in the gallery directory. If this file exists, we read 'name', 'caption' and 'order' from it and apply that metadata when generating the gallery. An entry must have at least 'name' to be considered valid. We cannot guarantee that yaml.safe_load_all() will return the elements in the same order that they are listed in the file. The user is warned about incorrectly formed YAML entries in metadata.yml (no 'name' found), and images found in the gallery directory which have no corresponding entry in metadata.yml. These images are appended to the end of the image list with the real filename as the caption.
It looks like your commit was misattributed. Please add the e-mail address you used for this commit (jmcp your domain) to your GitHub profile so your commits will appear as yours. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A few more things to fix.
docs/manual.rst
Outdated
Images in galleries may be provided with captions and given a specific | ||
ordering, by creating a file in the gallery directory called metadata.yml. | ||
This YAML file should contain a 'name' field for each image in the gallery, | ||
and (if desired) either or both of 'caption' and 'order'. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This needs a specific example for multiple files and cases.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
nikola/conf.py.in
Outdated
# named metadata.yml, is YAML and must contain at least a 'name' field. Other | ||
# recognised field names are 'order' and 'caption'. | ||
# Defaults to True | ||
# GALLERY_SORT_BY_META_FILE = True |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This doesn’t need to be a setting. If user provides a metadata.yml file and it contains order
fields, try to use them. Otherwise, don’t. I can’t think of a legitimate use case that would have a metadata file with order fields and not want to use it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Agreed
nikola/plugins/task/galleries.py
Outdated
img_titles.append(self.captions[fn]) | ||
else: | ||
img_titles.append(fn) | ||
self.logger.warn( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No need for a warning IMO.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Made this a self.logger.debug() call instead.
nikola/plugins/task/galleries.py
Outdated
# final element, so skip it | ||
if not img: | ||
continue | ||
if 'name' in img.keys(): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If that is a dict, you can use if 'name' in img:
— and please do that in other imgkeys
cases below
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
nikola/plugins/task/galleries.py
Outdated
@@ -568,7 +635,7 @@ def url_from_path(p): | |||
else: | |||
img_list, thumbs, img_titles = [], [], [] | |||
|
|||
photo_array = [] | |||
pre_photo = {} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
photo_info
perhaps?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Seems reasonable; done.
nikola/plugins/task/galleries.py
Outdated
photo_array.append(pre_photo.pop(entry)) | ||
# Do we have any orphan entries from metadata.yml? | ||
if len(pre_photo) > 0: | ||
for entry in pre_photo: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would sort entries here and below (in else
) so the ordering does not change due to dict randomness (on Python ≤3.5)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm uncertain about this suggestion.
We cannot sort photo_info
since it's a dict, and unless we've got an order (implicitly or explicitly) specified from metadata.yml
, then having unsorted output matches the existing behaviour. I'd prefer to leave this as-is.
nikola/plugins/task/galleries.py
Outdated
@@ -229,7 +236,18 @@ def gen_tasks(self): | |||
|
|||
image_name_list = [os.path.basename(p) for p in image_list] | |||
|
|||
if self.kw['use_filename_as_title']: | |||
if self.captions: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why is this a global variable? This should be handled in a gallery-specific way. Nikola can be run with threading, in which case breakage will occur.
Instead, return captions, order
from find_metadata()
and use that.
Also: how does this work for multilingual sites?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Now using order, captions = self.find_metadata(gallery)
as suggested, and adding both as elements of context
.
I haven't got a multilingual site to with, unfortunately. Looking through the code, though, I believe that the only place where non-en might get caught is in the call to json.dumps(). If we specify ensure_ascii=False
that should do the trick.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I believe that I've addressed all the changes requested.
This is my first github PR so I'm unsure if I have got everything figured out correctly in order for this PR to progress to integration - I would really appreciate feedback to let me know what I've missed, or what process steps I have mucked up. Thankyou!
.. code:: yaml | ||
--- | ||
name: ready-for-the-acid-wash.jpg |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this necessary? I would prefer something where users can specify only the files they want changed from the default.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've updated the docs to make it plain that you only need to list images for which a specific caption and/or order is required.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This looks pretty good! Localization support is very simple to add (I added instructions in comments). Other than that, there are a few minor style improvements to make.
PS. I still haven’t bothered to run and test this.
PPS. No, we really don’t require a lot of special effort from contributors. Authors/changelog and making sure it works is basically it.
nikola/plugins/task/galleries.py
Outdated
else: | ||
img_titles.append(fn) | ||
self.logger.debug( | ||
"Image {0} found in gallery but not listed " |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(Feel free to go past 79 characters per line, especially if adhering to the limit makes code look ugly. Keep it below 100 if you can, 120 max.)
nikola/plugins/task/galleries.py
Outdated
@@ -393,6 +411,51 @@ def create_galleries(self): | |||
'uptodate': [utils.config_changed(self.kw.copy(), 'nikola.plugins.task.galleries:mkdir')], | |||
} | |||
|
|||
def find_metadata(self, gallery): | |||
"""Search for a gallery metadata file. Returns list, dict if found.""" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please merge the docstring and the comment below it into one large, multiline docstring.
nikola/plugins/task/galleries.py
Outdated
else: | ||
order.append(img['name']) | ||
else: | ||
self.logger.warn("no 'name:' for ({0}) in {1}".format( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would argue this is error-and-exception worthy.
nikola/plugins/task/galleries.py
Outdated
@@ -220,6 +225,8 @@ def gen_tasks(self): | |||
self.kw[k] = self.site.GLOBAL_CONTEXT[k](lang) | |||
|
|||
context = {} | |||
context['order'] = order |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let’s make this translatable, it won’t be hard.
- create
order, captions
inside this loop, so you can - pass
lang
tofind_metadata
, which - will use it to get the correct language path (I’ll comment on it below)
nikola/plugins/task/galleries.py
Outdated
# use an empty string. | ||
# Returns a list (ordering) and dict (captions). | ||
|
||
meta_path = os.path.join(gallery, "metadata.yml") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
base_meta_path = os.path.join(gallery, "metadata.yml")
localized_meta_path = utils.get_translation_candidate(self.site.config, base_meta_path, lang)
And then (pseudocode):
if localized path exists:
used_path = localized
else if base path exists:
used_path = base
else:
return [], {}
# all the other logic here, with `used_path`
nikola/plugins/task/galleries.py
Outdated
if os.path.isfile(meta_path): | ||
self.logger.debug("Using {0} for gallery {1}".format( | ||
meta_path, gallery)) | ||
self.meta_path = meta_path |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
One more global reference to remove here.
It is now only necessary to specify an image filename in metadata.yml if you really want to have a specific caption or ordering for an image. Updated manual to make this clear. Update galleries.py to make it an error to provide a YAML entry which does not have a name: field.
nikola/plugins/task/galleries.py
Outdated
photo_array.append(photo_info.pop(entry)) | ||
# Do we have any orphan entries from metadata.yml, or | ||
# are the files from the gallery not listed in metadata.yml? | ||
if len(photo_info) > 0: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if photo_info:
would be better spelling of that (I fixed it)
Thanks for contributing! You may still want to add the e-mail address you used for the first two commits to your GitHub profile so your commits will appear as yours. |
For galleries: this change provides support for per-image captions
and for specifying an order to display images in.
Pull Request Checklist
Description
Implements issue #3017.