You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

173 lines
4.6 KiB

"""An elementary Web gallery generator using Masonry and Lightbox."""
import argparse
import json
import os
from PIL import Image
SUPPORTED_TYPES = ("jpg", "jpeg", "png", "gif", "webp")
JQUERY_PATH = "/libs/jquery/jquery.min.js"
MASONRY_PATH = "/libs/masonry/masonry.pkgd.min.js"
IMAGESLOADED_PATH = "/libs/masonry/imagesloaded.pkgd.min.js"
LIGHTBOX_PATH = "/libs/lightbox2/js/lightbox.min.js"
LIGHTBOX_CSS_PATH = "/libs/lightbox2/css/lightbox.min.css"
HTML = """\
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>{title}</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<style>
{css}
</style>
<!-- jQuery -->
<script src="{jquery}"></script>
<!-- Masonry & ImagesLoaded -->
<script src="{masonry}"></script>
<script src="{imagesloaded}"></script>
<!-- Lightbox2 -->
<link href="{lightbox_css}" rel="stylesheet">
<script src="{lightbox}"></script>
</head>
<body>
<div class="masonry">
</div>
<script>
{js}
</script>
</body>
</html>
"""
CSS = """\
body {
background: black;
}
/* 4 columns by default */
.masonry {
margin: auto;
width: 1470px;
}
.masonry-item img {
margin-bottom: 10px;
width: 360px;
}
/* 3 columns on small desktop screens */
@media only screen and (max-width: 1500px) {
.masonry { width: 1100px; }
}
/* 2 columns on medium-size screens */
@media only screen and (max-width: 1200px) {
.masonry { width: 730px; }
}
/* 1 column on mobile */
@media only screen and (max-width: 768px) {
.masonry { width: 100%; }
.masonry-item { width: 100%; }
.masonry-item img { width: 100%; }
}
"""
JS = """\
var dirname = path => path.replace(/\\\\/g,'/').replace(/\\/[^\\/]*$/, '');
function initMasonry(json) {
var $grid = $('.masonry');
for (var i = 0; i < json.length; i++) {
var entry = json[i];
var $img = $(document.createElement('img'));
$img.attr('src', entry.src);
var $link = $(document.createElement('a'));
$link.attr({
'href': entry.src,
'data-lightbox': 'gallery',
'data-title': entry.title,
});
$link.append($img);
var $container = $(document.createElement('div'));
$container.addClass('masonry-item');
$container.append($link);
$grid.append($container);
}
$grid.masonry({
itemSelector: '.masonry-item',
columnWidth: 360,
gutter: 10,
});
$grid.imagesLoaded().progress(() => $grid.masonry('layout'));
}
var loc = dirname(location.pathname) + '/data.json';
$(document).ready(() => {
fetch(loc)
.then(response => response.json())
.then(json => initMasonry(json));
});
"""
def gen_gallery(dirpath: str, title: str, libs: dict):
entries = []
for filename in os.listdir(dirpath):
ext = os.path.splitext(filename)[1][1:].lower()
if ext not in SUPPORTED_TYPES:
continue
image = Image.open(os.path.join(dirpath, filename))
dimensions = image.size
entries.append({
"src": filename,
"w": dimensions[0],
"h": dimensions[1],
"title": "",
})
try:
with open(os.path.join(dirpath, "data.json"), "wt") as data_file:
json.dump(entries, data_file)
except OSError as exc:
exit(f"Can't write data.json file: {exc}")
print("Data JSON saved.")
try:
with open(os.path.join(dirpath, "index.html"), "wt") as index_file:
index_file.write(HTML.format(title=title, css=CSS, js=JS, **libs))
except OSError as exc:
exit(f"Can't write index.html file: {exc}")
print("Web page saved.")
def main():
ap = argparse.ArgumentParser()
ap.add_argument("dir", help="directory with the photos")
ap.add_argument("--title", default="EmlGallery", help="page title")
ap.add_argument("--jquery", help="Web path to JQuery library")
ap.add_argument("--masonry", help="Web path to Masonry library")
ap.add_argument("--imagesloaded", help="Web path to ImagesLoaded library")
ap.add_argument("--lightbox", help="Web path to Lightbox2 library")
ap.add_argument("--lightbox-css", help="Web path to Lightbox2 CSS")
args = ap.parse_args()
libs = {
"jquery": args.jquery or JQUERY_PATH,
"masonry": args.masonry or MASONRY_PATH,
"imagesloaded": args.imagesloaded or IMAGESLOADED_PATH,
"lightbox": args.lightbox or LIGHTBOX_PATH,
"lightbox_css": args.lightbox_css or LIGHTBOX_CSS_PATH,
}
gen_gallery(args.dir, args.title, libs)
if __name__ == "__main__":
main()