sigal 2.4__py3-none-any.whl → 2.5__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (55) hide show
  1. sigal/__main__.py +6 -1
  2. sigal/gallery.py +24 -9
  3. sigal/image.py +21 -4
  4. sigal/plugins/compress_assets.py +4 -3
  5. sigal/plugins/encrypt/encrypt.py +1 -1
  6. sigal/plugins/encrypt/endec.py +2 -2
  7. sigal/plugins/extended_caching.py +5 -1
  8. sigal/plugins/nomedia.py +1 -1
  9. sigal/plugins/titleregexp.py +2 -2
  10. sigal/plugins/zip_gallery.py +1 -1
  11. sigal/settings.py +12 -1
  12. sigal/templates/sigal.conf.py +9 -11
  13. sigal/themes/default/templates/description.html +29 -0
  14. sigal/themes/default/templates/footer.html +3 -0
  15. sigal/themes/galleria/templates/album_items.html +2 -23
  16. sigal/themes/photoswipe/static/photoswipe-dynamic-caption-plugin.esm.js +414 -0
  17. sigal/themes/photoswipe/static/photoswipe-dynamic-caption-plugin.esm.min.js +5 -0
  18. sigal/themes/photoswipe/static/photoswipe-fullscreen.esm.js +129 -0
  19. sigal/themes/photoswipe/static/photoswipe-fullscreen.esm.min.js +8 -0
  20. sigal/themes/photoswipe/static/photoswipe-lightbox.esm.js +1960 -0
  21. sigal/themes/photoswipe/static/photoswipe-lightbox.esm.js.map +1 -0
  22. sigal/themes/photoswipe/static/photoswipe-lightbox.esm.min.js +5 -0
  23. sigal/themes/photoswipe/static/photoswipe-video-plugin.esm.js +257 -0
  24. sigal/themes/photoswipe/static/photoswipe-video-plugin.esm.min.js +1 -0
  25. sigal/themes/photoswipe/static/photoswipe.css +385 -140
  26. sigal/themes/photoswipe/static/photoswipe.esm.js +7081 -0
  27. sigal/themes/photoswipe/static/photoswipe.esm.js.map +1 -0
  28. sigal/themes/photoswipe/static/photoswipe.esm.min.js +5 -0
  29. sigal/themes/photoswipe/static/styles.css +53 -0
  30. sigal/themes/photoswipe/templates/album.html +69 -74
  31. sigal/utils.py +4 -1
  32. sigal/version.py +16 -3
  33. sigal/video.py +2 -2
  34. sigal/writer.py +10 -2
  35. {sigal-2.4.dist-info → sigal-2.5.dist-info}/METADATA +19 -24
  36. {sigal-2.4.dist-info → sigal-2.5.dist-info}/RECORD +40 -42
  37. {sigal-2.4.dist-info → sigal-2.5.dist-info}/WHEEL +1 -1
  38. sigal/plugins/upload_s3.py +0 -106
  39. sigal/themes/photoswipe/static/app.js +0 -214
  40. sigal/themes/photoswipe/static/default-skin/default-skin.css +0 -485
  41. sigal/themes/photoswipe/static/default-skin/default-skin.css.map +0 -10
  42. sigal/themes/photoswipe/static/default-skin/default-skin.png +0 -0
  43. sigal/themes/photoswipe/static/default-skin/default-skin.svg +0 -36
  44. sigal/themes/photoswipe/static/default-skin/preloader.gif +0 -0
  45. sigal/themes/photoswipe/static/echo/blank.gif +0 -0
  46. sigal/themes/photoswipe/static/echo/echo.js +0 -135
  47. sigal/themes/photoswipe/static/echo/echo.min.js +0 -2
  48. sigal/themes/photoswipe/static/photoswipe-ui-default.js +0 -871
  49. sigal/themes/photoswipe/static/photoswipe-ui-default.min.js +0 -1
  50. sigal/themes/photoswipe/static/photoswipe.css.map +0 -10
  51. sigal/themes/photoswipe/static/photoswipe.js +0 -3592
  52. sigal/themes/photoswipe/static/photoswipe.min.js +0 -1
  53. {sigal-2.4.dist-info → sigal-2.5.dist-info}/LICENSE +0 -0
  54. {sigal-2.4.dist-info → sigal-2.5.dist-info}/entry_points.txt +0 -0
  55. {sigal-2.4.dist-info → sigal-2.5.dist-info}/top_level.txt +0 -0
sigal/__main__.py CHANGED
@@ -25,6 +25,7 @@ import pathlib
25
25
  import socketserver
26
26
  import sys
27
27
  import time
28
+ import webbrowser
28
29
  from http import server
29
30
 
30
31
  import click
@@ -227,7 +228,8 @@ def build(
227
228
  show_default=True,
228
229
  help="Configuration file",
229
230
  )
230
- def serve(destination, port, config):
231
+ @option("-b", "--browser", is_flag=True, help="Open in your default browser")
232
+ def serve(destination, port, config, browser):
231
233
  """Run a simple web server."""
232
234
  if os.path.exists(destination):
233
235
  pass
@@ -253,6 +255,9 @@ def serve(destination, port, config):
253
255
  httpd = socketserver.TCPServer(("", port), Handler, False)
254
256
  print(f" * Running on http://127.0.0.1:{port}/")
255
257
 
258
+ if browser:
259
+ webbrowser.open(f"http://127.0.0.1:{port}/")
260
+
256
261
  try:
257
262
  httpd.allow_reuse_address = True
258
263
  httpd.server_bind()
sigal/gallery.py CHANGED
@@ -45,7 +45,13 @@ from natsort import natsort_keygen, ns
45
45
  from PIL import Image as PILImage
46
46
 
47
47
  from . import image, signals, video
48
- from .image import get_exif_tags, get_image_metadata, get_size, process_image
48
+ from .image import (
49
+ EXIF_EXTENSIONS,
50
+ get_exif_tags,
51
+ get_image_metadata,
52
+ get_size,
53
+ process_image,
54
+ )
49
55
  from .settings import Status, get_thumb
50
56
  from .utils import (
51
57
  Devnull,
@@ -264,7 +270,7 @@ class Image(Media):
264
270
  datetime_format = self.settings["datetime_format"]
265
271
  return (
266
272
  get_exif_tags(self.raw_exif, datetime_format=datetime_format)
267
- if self.raw_exif and self.src_ext in (".jpg", ".jpeg")
273
+ if self.raw_exif and self.src_ext in EXIF_EXTENSIONS
268
274
  else None
269
275
  )
270
276
 
@@ -289,7 +295,7 @@ class Image(Media):
289
295
  @cached_property
290
296
  def raw_exif(self):
291
297
  """If not `None`, contains the raw EXIF tags."""
292
- if self.src_ext in (".jpg", ".jpeg"):
298
+ if self.src_ext in EXIF_EXTENSIONS:
293
299
  return self.file_metadata["exif"]
294
300
 
295
301
  @cached_property
@@ -486,6 +492,7 @@ class Album:
486
492
  reverse = self.settings["albums_sort_reverse"]
487
493
 
488
494
  if "sort" in self.meta:
495
+ # override default sort order from settings
489
496
  albums_sort_attr = self.meta["sort"][0]
490
497
  if albums_sort_attr[0] == "-":
491
498
  albums_sort_attr = albums_sort_attr[1:]
@@ -515,7 +522,7 @@ class Album:
515
522
  continue
516
523
  return ""
517
524
 
518
- key = natsort_keygen(key=sort_key, alg=ns.LOCALE)
525
+ key = natsort_keygen(key=sort_key, alg=ns.SIGNED | ns.LOCALE)
519
526
  self.subdirs.sort(key=key, reverse=reverse)
520
527
 
521
528
  signals.albums_sorted.send(self)
@@ -530,11 +537,13 @@ class Album:
530
537
  elif medias_sort_attr.startswith("meta."):
531
538
  meta_key = medias_sort_attr.split(".", 1)[1]
532
539
  key = natsort_keygen(
533
- key=lambda s: s.meta.get(meta_key, [""])[0], alg=ns.LOCALE
540
+ key=lambda s: s.meta.get(meta_key, [""])[0],
541
+ alg=ns.SIGNED | ns.LOCALE,
534
542
  )
535
543
  else:
536
544
  key = natsort_keygen(
537
- key=lambda s: getattr(s, medias_sort_attr), alg=ns.LOCALE
545
+ key=lambda s: getattr(s, medias_sort_attr),
546
+ alg=ns.SIGNED | ns.LOCALE,
538
547
  )
539
548
 
540
549
  self.medias.sort(key=key, reverse=self.settings["medias_sort_reverse"])
@@ -734,6 +743,11 @@ class Gallery:
734
743
  fnmatch.fnmatch(relpath, ignore) for ignore in ignore_dirs
735
744
  ):
736
745
  self.logger.info("Ignoring %s", relpath)
746
+ # Remove sub-directories
747
+ for d in dirs[:]:
748
+ path = join(relpath, d) if relpath != "." else d
749
+ if path in albums.keys():
750
+ del albums[path]
737
751
  continue
738
752
 
739
753
  # Remove files that match the ignore_files settings
@@ -767,7 +781,7 @@ class Gallery:
767
781
 
768
782
  with progressbar(
769
783
  albums.values(),
770
- label="%16s" % "Sorting albums",
784
+ label="{:>16s}".format("Sorting albums"),
771
785
  file=self.progressbar_target,
772
786
  ) as progress_albums:
773
787
  for album in progress_albums:
@@ -775,7 +789,7 @@ class Gallery:
775
789
 
776
790
  with progressbar(
777
791
  albums.values(),
778
- label="%16s" % "Sorting media",
792
+ label="{:>16s}".format("Sorting medias"),
779
793
  file=self.progressbar_target,
780
794
  ) as progress_albums:
781
795
  for album in progress_albums:
@@ -891,12 +905,13 @@ class Gallery:
891
905
 
892
906
  if self.settings["write_html"]:
893
907
  album_writer = AlbumPageWriter(self.settings, index_title=self.title)
908
+ album_writer.copy_theme_files()
894
909
  album_list_writer = AlbumListPageWriter(
895
910
  self.settings, index_title=self.title
896
911
  )
897
912
  with progressbar(
898
913
  self.albums.values(),
899
- label="%16s" % "Writing files",
914
+ label="{:>16s}".format("Writing files"),
900
915
  item_show_func=log_func,
901
916
  show_eta=False,
902
917
  file=self.progressbar_target,
sigal/image.py CHANGED
@@ -44,11 +44,21 @@ from PIL.TiffImagePlugin import IFDRational
44
44
  from pilkit.processors import Transpose
45
45
  from pilkit.utils import save_image
46
46
 
47
+ try:
48
+ from pillow_heif import HeifImagePlugin # noqa: F401
49
+
50
+ HAS_HEIF = True
51
+ except ImportError:
52
+ HAS_HEIF = False
53
+
47
54
  from . import signals, utils
55
+ from .settings import Status
48
56
 
49
57
  # Force loading of truncated files
50
58
  ImageFile.LOAD_TRUNCATED_IMAGES = True
51
59
 
60
+ EXIF_EXTENSIONS = (".jpg", ".jpeg", ".heic")
61
+
52
62
 
53
63
  def _has_exif_tags(img):
54
64
  return hasattr(img, "info") and "exif" in img.info
@@ -66,8 +76,7 @@ def _read_image(file_path):
66
76
 
67
77
  for w in caught_warnings:
68
78
  logger.warning(
69
- f"PILImage reported a warning for file {file_path}\n"
70
- f"{w.category}: {w.message}"
79
+ f"Pillow reported a warning for file {file_path}\n{w.category}: {w.message}"
71
80
  )
72
81
  return im
73
82
 
@@ -180,6 +189,11 @@ def process_image(media):
180
189
  options = media.settings["jpg_options"]
181
190
  elif media.src_ext == ".png":
182
191
  options = {"optimize": True}
192
+ elif media.src_ext == ".heic" and not HAS_HEIF:
193
+ logger.warning(
194
+ f"cannot open {media.src_path}, pillow-heif is needed to open .heic files"
195
+ )
196
+ return Status.FAILURE
183
197
  else:
184
198
  options = {}
185
199
 
@@ -220,7 +234,10 @@ def get_exif_data(filename):
220
234
 
221
235
  try:
222
236
  with warnings.catch_warnings(record=True) as caught_warnings:
223
- exif = img._getexif() or {}
237
+ exif = {}
238
+ exifdata = img.getexif()
239
+ if exifdata:
240
+ exif = exifdata._get_merged_dict()
224
241
  except ZeroDivisionError:
225
242
  logger.warning("Failed to read EXIF data.")
226
243
  return None
@@ -290,7 +307,7 @@ def get_image_metadata(filename):
290
307
  logger.error("Could not open image %s metadata: %s", filename, e)
291
308
  else:
292
309
  try:
293
- if os.path.splitext(filename)[1].lower() in (".jpg", ".jpeg"):
310
+ if os.path.splitext(filename)[1].lower() in EXIF_EXTENSIONS:
294
311
  exif = get_exif_data(img)
295
312
  except Exception as e:
296
313
  logger.warning("Could not read EXIF data from %s: %s", filename, e)
@@ -106,9 +106,10 @@ class GZipCompressor(BaseCompressor):
106
106
  suffix = "gz"
107
107
 
108
108
  def do_compress(self, filename, compressed_filename):
109
- with open(filename, "rb") as f_in, gzip.open(
110
- compressed_filename, "wb"
111
- ) as f_out:
109
+ with (
110
+ open(filename, "rb") as f_in,
111
+ gzip.open(compressed_filename, "wb") as f_out,
112
+ ):
112
113
  shutil.copyfileobj(f_in, f_out)
113
114
 
114
115
 
@@ -200,7 +200,7 @@ def encrypt_files(settings, config, cache, albums, progressbar_target):
200
200
  medias = list(chain.from_iterable(albums.values()))
201
201
  with progressbar(
202
202
  medias,
203
- label="%16s" % "Encrypting files",
203
+ label="{:>16s}".format("Encrypting files"),
204
204
  file=progressbar_target,
205
205
  show_eta=True,
206
206
  ) as medias:
@@ -66,7 +66,7 @@ def dispatchargs(decorated):
66
66
 
67
67
  def encrypt(key: bytes, infile: BinaryIO, outfile: BinaryIO, tag: bytes):
68
68
  if len(key) != 128 / 8:
69
- raise ValueError("Unsupported key length: %d" % len(key))
69
+ raise ValueError(f"Unsupported key length: {len(key)}")
70
70
  aesgcm = AESGCM(key)
71
71
  iv = os.urandom(12)
72
72
  plaintext = infile
@@ -80,7 +80,7 @@ def encrypt(key: bytes, infile: BinaryIO, outfile: BinaryIO, tag: bytes):
80
80
 
81
81
  def decrypt(key: bytes, infile: BinaryIO, outfile: BinaryIO, tag: bytes):
82
82
  if len(key) != 128 / 8:
83
- raise ValueError("Unsupported key length: %d" % len(key))
83
+ raise ValueError(f"Unsupported key length: {len(key)}")
84
84
  aesgcm = AESGCM(key)
85
85
  ciphertext = infile
86
86
  plaintext = outfile
@@ -18,7 +18,7 @@
18
18
  # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
19
19
  # IN THE SOFTWARE.
20
20
 
21
- """ Decreases the time needed to build large galleries (e.g.: 25k images in
21
+ """Decreases the time needed to build large galleries (e.g.: 25k images in
22
22
  2.5s instead of 30s)
23
23
 
24
24
  This plugin allows extended caching, which is useful for large galleries. Once
@@ -78,6 +78,8 @@ def load_metadata(album):
78
78
  media.file_metadata = data["file_metadata"]
79
79
  if "exif" in data:
80
80
  media.exif = data["exif"]
81
+ if "input_size" in data:
82
+ media.input_size = data["input_size"]
81
83
 
82
84
  try:
83
85
  mod_date = int(get_mod_date(media.markdown_metadata_filepath))
@@ -134,6 +136,8 @@ def save_cache(gallery):
134
136
  data["file_metadata"] = media.file_metadata
135
137
  if hasattr(media, "exif"):
136
138
  data["exif"] = media.exif
139
+ if hasattr(media, "input_size"):
140
+ data["input_size"] = media.input_size
137
141
 
138
142
  try:
139
143
  meta_mod_date = int(get_mod_date(media.markdown_metadata_filepath))
sigal/plugins/nomedia.py CHANGED
@@ -18,7 +18,7 @@
18
18
  # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
19
19
  # IN THE SOFTWARE.
20
20
 
21
- """ This plugin offers more fine-grained control over exluded images and
21
+ """This plugin offers more fine-grained control over exluded images and
22
22
  folders, similarly to how it's handled on Android.
23
23
 
24
24
  To ignore a folder or image put a ``.nomedia`` file next to it in its parent
@@ -18,7 +18,7 @@
18
18
  # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
19
19
  # IN THE SOFTWARE.
20
20
 
21
- """ This plugin modifies titles of galleries by using regular-expressions and
21
+ """This plugin modifies titles of galleries by using regular-expressions and
22
22
  simple string or character replacements. It is acting in two phases: First, all
23
23
  regular-expression-based modifications are carried out, second, string/character
24
24
  replacements are done.
@@ -74,7 +74,7 @@ def titleregexp(album):
74
74
 
75
75
  for r in cfg.get("regexp"):
76
76
  album.title, n = re.subn(
77
- r.get("search"), r.get("replace"), album.title, r.get("count", 0)
77
+ r.get("search"), r.get("replace"), album.title, count=r.get("count", 0)
78
78
  )
79
79
  total += n
80
80
 
@@ -18,7 +18,7 @@
18
18
  # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
19
19
  # IN THE SOFTWARE.
20
20
 
21
- """ This plugin controls the generation of a ZIP archive for a gallery
21
+ """This plugin controls the generation of a ZIP archive for a gallery
22
22
 
23
23
  If the ``zip_gallery`` setting is set, it contains the location of a zip
24
24
  archive with all original images of the corresponding directory.
sigal/settings.py CHANGED
@@ -30,9 +30,11 @@ _DEFAULT_CONFIG = {
30
30
  "albums_sort_attr": "name",
31
31
  "albums_sort_reverse": False,
32
32
  "autorotate_images": True,
33
+ "autoplay": False,
33
34
  "colorbox_column_size": 3,
34
35
  "copy_exif_data": False,
35
36
  "datetime_format": "%c",
37
+ "display_timestamp": False,
36
38
  "destination": "_build",
37
39
  "files_to_copy": (),
38
40
  "galleria_theme": "classic",
@@ -40,7 +42,16 @@ _DEFAULT_CONFIG = {
40
42
  "google_tag_manager": "",
41
43
  "ignore_directories": [],
42
44
  "ignore_files": [],
43
- "img_extensions": [".jpg", ".jpeg", ".png", ".gif", ".tif", ".tiff", ".webp"],
45
+ "img_extensions": [
46
+ ".jpg",
47
+ ".jpeg",
48
+ ".png",
49
+ ".gif",
50
+ ".heic",
51
+ ".tif",
52
+ ".tiff",
53
+ ".webp",
54
+ ],
44
55
  "img_processor": "ResizeToFit",
45
56
  "img_size": (640, 480),
46
57
  "img_format": None,
@@ -39,6 +39,9 @@ theme = "galleria"
39
39
  # Path to a CSS file that can be used to customize themes
40
40
  # user_css =
41
41
 
42
+ # Enable autoplay (galleria only)
43
+ # autoplay = False
44
+
42
45
  # ----------------
43
46
  # Image processing (ignored if use_orig = True)
44
47
  # ----------------
@@ -63,7 +66,7 @@ img_size = (800, 600)
63
66
  # map_height = '500px'
64
67
 
65
68
  # File extensions that should be treated as images
66
- # img_extensions = ['.jpg', '.jpeg', '.png', '.gif']
69
+ # img_extensions = [".jpg", ".jpeg", ".png", ".gif", ".heic", ".tif", ".tiff", ".webp"]
67
70
 
68
71
  # Pilkit processor used to resize the image
69
72
  # (see http://pilkit.readthedocs.org/en/latest/#processors)
@@ -86,6 +89,9 @@ img_size = (800, 600)
86
89
  # https://docs.python.org/3/library/datetime.html#strftime-strptime-behavior
87
90
  # datetime_format = '%c'
88
91
 
92
+ # Display generated datetime in the resulting output
93
+ # display_timestamp = False
94
+
89
95
  # Jpeg options
90
96
  # jpg_options = {'quality': 85,
91
97
  # 'optimize': True,
@@ -128,7 +134,7 @@ thumb_size = (280, 210)
128
134
  # thumb_video_black_max_colors = 4
129
135
 
130
136
  # Keep original image (default: False)
131
- # keep_orig = True
137
+ # keep_orig = False
132
138
 
133
139
  # Subdirectory for original images
134
140
  # orig_dir = 'original'
@@ -158,7 +164,7 @@ thumb_size = (280, 210)
158
164
  # Filter directories and files.
159
165
  # The settings take a list of patterns matched with the fnmatch module on the
160
166
  # path relative to the source directory:
161
- # http://docs.python.org/2/library/fnmatch.html
167
+ # http://docs.python.org/3/library/fnmatch.html
162
168
  ignore_directories = []
163
169
  ignore_files = []
164
170
 
@@ -281,7 +287,6 @@ ignore_files = []
281
287
  # 'sigal.plugins.media_page',
282
288
  # 'sigal.plugins.nomedia',
283
289
  # 'sigal.plugins.nonmedia_files',
284
- # 'sigal.plugins.upload_s3',
285
290
  # 'sigal.plugins.watermark',
286
291
  # 'sigal.plugins.zip_gallery',
287
292
  # ]
@@ -317,13 +322,6 @@ ignore_files = []
317
322
  # 'thumb_font_size': 40, # only applies when a font is selected
318
323
  # }
319
324
 
320
- # Settings for upload to s3 plugin
321
- # upload_s3_options = {
322
- # 'bucket': 'my-bucket',
323
- # 'policy': 'public-read',
324
- # 'overwrite': False
325
- # }
326
-
327
325
  # Set zip_gallery to either False or a file name. The file name can
328
326
  # be formatted python style with an 'album' variable, for example
329
327
  # '{album.name}.zip'. The final archive will contain all resized or
@@ -0,0 +1,29 @@
1
+ {% macro img_description(media, with_big=True) -%}
2
+ {%- if with_big and media.big -%}
3
+ <a href='{{ media.big_url }}'>Full size</a>
4
+ {%- endif -%}
5
+ {%- if media.description -%}
6
+ <br>{{ media.description }}
7
+ {%- endif -%}
8
+ {%- if media.exif -%}
9
+ <div class='film-meta'>
10
+ {%- if media.exif.iso -%}
11
+ <abbr title='film speed'>{{ media.exif.iso }}</abbr> {%- endif -%}
12
+ {%- if media.exif.exposure -%}
13
+ <abbr title='exposure'>{{ media.exif.exposure }}</abbr> {%- endif -%}
14
+ {%- if media.exif.fstop -%}
15
+ <abbr title='aperture'>{{ media.exif.fstop }}</abbr> {%- endif -%}
16
+ {%- if media.exif.focal -%}
17
+ <abbr title='focal length'>{{ media.exif.focal }}</abbr> {%- endif -%}
18
+ </div>
19
+ {%- if media.exif.gps -%}
20
+ <a title='location' href='https://www.openstreetmap.org/?mlat={{ media.exif.gps.lat }}&amp;mlon={{ media.exif.gps.lon}}&amp;zoom=12&amp;layers=M' target='_blank' class='map' >{{ 'N{:.6f}'.format(media.exif.gps.lat) if media.exif.gps.lat > 0 else 'S{:.6f}'.format(-media.exif.gps.lat) }}{{ 'E{:.6f}'.format(media.exif.gps.lon) if media.exif.gps.lon > 0 else 'W{:.6f}'.format(-media.exif.gps.lon) }}</a>
21
+ {%- endif -%}
22
+ {%- if media.exif.Make or media.exif.Model -%}
23
+ <abbr title='camera make and model'>{{ media.exif.Make }} {{ media.exif.Model }}</abbr>
24
+ {%- endif -%}
25
+ {%- if media.exif.datetime -%}
26
+ <abbr title='date'>{{ media.exif.datetime }}</abbr>
27
+ {%- endif -%}
28
+ {% endif %}
29
+ {%- endmacro %}
@@ -12,5 +12,8 @@
12
12
  <span><a href={{ settings.atom_feed.feed_url }}>Atom Feed</a></span>
13
13
  {% endif %}
14
14
  {% endif %}
15
+ {% if settings.display_timestamp %}
16
+ @ {{ generated_timestamp }}
17
+ {% endif %}
15
18
  </p>
16
19
  </footer>
@@ -1,3 +1,4 @@
1
+ {% from 'description.html' import img_description %}
1
2
  <div class="icons">
2
3
  <a id="fullscreen"><img src="{{ theme.url }}/img/fullscreen.png"
3
4
  title="Fullscreen" alt="Fullscreen (f)" /></a>
@@ -17,29 +18,6 @@
17
18
 
18
19
  {% block late_js %}
19
20
  {% if album.medias %}
20
- {% macro img_description(media) -%}
21
- {%- if media.big -%}<a href='{{ media.big_url }}'>Full size</a>{%- endif -%}
22
- {# clean up tags and whitespace, including newlines, in the description #}
23
- {%- if media.description -%}<br>{{ media.description | striptags }}{%- endif -%}
24
- {%- if media.exif -%}
25
- <div class='film-meta'>
26
- {%- if media.exif.iso -%}<abbr title='film speed'>{{ media.exif.iso }}</abbr> {%- endif -%}
27
- {%- if media.exif.exposure -%}<abbr title='exposure'>{{ media.exif.exposure }}</abbr> {%- endif -%}
28
- {%- if media.exif.fstop -%}<abbr title='aperture'>{{ media.exif.fstop }}</abbr> {%- endif -%}
29
- {%- if media.exif.focal -%}<abbr title='focal length'>{{ media.exif.focal }}</abbr> {%- endif -%}
30
- </div>
31
- {%- if media.exif.gps -%}
32
- <a title='location' href='https://www.openstreetmap.org/?mlat={{ media.exif.gps.lat }}&amp;mlon={{ media.exif.gps.lon}}&amp;zoom=12&amp;layers=M' target='_blank' class='map' >{{ 'N{:.6f}'.format(media.exif.gps.lat) if media.exif.gps.lat > 0 else 'S{:.6f}'.format(-media.exif.gps.lat) }}{{ 'E{:.6f}'.format(media.exif.gps.lon) if media.exif.gps.lon > 0 else 'W{:.6f}'.format(-media.exif.gps.lon) }}</a>
33
- {%- endif -%}
34
- {%- if media.exif.Make or media.exif.Model -%}
35
- <abbr title='camera make and model'>{{ media.exif.Make }} {{ media.exif.Model }}</abbr>
36
- {%- endif -%}
37
- {%- if media.exif.datetime -%}
38
- <abbr title='date'>{{ media.exif.datetime }}</abbr>
39
- {%- endif -%}
40
- {% endif %}
41
- {%- endmacro %}
42
-
43
21
  <script src="{{ theme.url }}/jquery-3.3.1.min.js"></script>
44
22
  <script src="{{ theme.url }}/galleria.min.js"></script>
45
23
  <script src="{{ theme.url }}/themes/{{ settings.galleria_theme }}/galleria.{{ settings.galleria_theme }}.min.js"></script>
@@ -93,6 +71,7 @@
93
71
  });
94
72
 
95
73
  Galleria.configure({
74
+ {% if settings.autoplay %}autoplay: true,{% endif %}
96
75
  imageCrop: false,
97
76
  transition: "fade",
98
77
  thumbnails: "lazy"