mirror of
https://github.com/greflm13/StaticGalleryBuilder.git
synced 2026-02-05 11:09:26 +00:00
Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
67a9058b7d
|
@@ -98,8 +98,32 @@ def initialize_metadata(folder: str) -> dict[str, dict[str, int]]:
|
|||||||
# remove old sizelist if it exists
|
# remove old sizelist if it exists
|
||||||
sizelist_path = os.path.join(folder, ".sizelist.json")
|
sizelist_path = os.path.join(folder, ".sizelist.json")
|
||||||
if os.path.exists(sizelist_path):
|
if os.path.exists(sizelist_path):
|
||||||
|
with open(sizelist_path, "r") as sizelist:
|
||||||
|
metadata = json.loads(sizelist.read())
|
||||||
logger.warning("found old .sizelist.json, removing it...", extra={"path": sizelist_path})
|
logger.warning("found old .sizelist.json, removing it...", extra={"path": sizelist_path})
|
||||||
os.remove(sizelist_path)
|
os.remove(sizelist_path)
|
||||||
|
|
||||||
|
# convert from old metadata format
|
||||||
|
if "images" not in metadata and "subfolders" not in metadata:
|
||||||
|
images = metadata.copy()
|
||||||
|
metadata = {}
|
||||||
|
metadata["images"] = images
|
||||||
|
elif "images" not in metadata:
|
||||||
|
metadata["images"] = {}
|
||||||
|
for k, v in metadata["images"].items():
|
||||||
|
if "width" in v:
|
||||||
|
metadata["images"][k]["w"] = v["width"]
|
||||||
|
del metadata["images"][k]["width"]
|
||||||
|
if "height" in v:
|
||||||
|
metadata["images"][k]["h"] = v["height"]
|
||||||
|
del metadata["images"][k]["height"]
|
||||||
|
if "tags" not in v:
|
||||||
|
metadata["images"][k]["tags"] = []
|
||||||
|
if "exifdata" not in v:
|
||||||
|
metadata["images"][k]["exifdata"] = None
|
||||||
|
if "xmp" not in v:
|
||||||
|
metadata["images"][k]["xmp"] = None
|
||||||
|
|
||||||
return metadata
|
return metadata
|
||||||
|
|
||||||
|
|
||||||
@@ -144,7 +168,7 @@ def get_image_info(item: str, folder: str) -> dict[str, Any]:
|
|||||||
except UnidentifiedImageError:
|
except UnidentifiedImageError:
|
||||||
logger.error("cannot identify image file", extra={"file": file})
|
logger.error("cannot identify image file", extra={"file": file})
|
||||||
print(f"cannot identify image file: {file}")
|
print(f"cannot identify image file: {file}")
|
||||||
return {"width": None, "height": None, "tags": None, "exifdata": None, "xmp": None}
|
return {"w": None, "h": None, "tags": None, "exifdata": None, "xmp": None}
|
||||||
if exif:
|
if exif:
|
||||||
logger.info("extracting EXIF data", extra={"file": file})
|
logger.info("extracting EXIF data", extra={"file": file})
|
||||||
ifd = exif.get_ifd(ExifTags.IFD.Exif)
|
ifd = exif.get_ifd(ExifTags.IFD.Exif)
|
||||||
@@ -220,7 +244,7 @@ def get_image_info(item: str, folder: str) -> dict[str, Any]:
|
|||||||
pass
|
pass
|
||||||
if None in tags:
|
if None in tags:
|
||||||
tags.remove(None)
|
tags.remove(None)
|
||||||
return {"width": width, "height": height, "tags": tags, "exifdata": exifdata, "xmp": xmp}
|
return {"w": width, "h": height, "tags": tags, "exifdata": exifdata, "xmp": xmp}
|
||||||
|
|
||||||
|
|
||||||
def nested_dict():
|
def nested_dict():
|
||||||
@@ -318,25 +342,23 @@ def process_image(item: str, folder: str, _args: Args, baseurl: str, metadata: d
|
|||||||
dict[str, Any]: dictionary containing image details for HTML rendering.
|
dict[str, Any]: dictionary containing image details for HTML rendering.
|
||||||
"""
|
"""
|
||||||
extsplit = os.path.splitext(item)
|
extsplit = os.path.splitext(item)
|
||||||
if item not in metadata or _args.reread_metadata:
|
if item not in metadata["images"] or _args.reread_metadata:
|
||||||
metadata[item] = get_image_info(item, folder)
|
metadata["images"][item] = get_image_info(item, folder)
|
||||||
sidecarfile = os.path.join(folder, item + ".xmp")
|
sidecarfile = os.path.join(folder, item + ".xmp")
|
||||||
if os.path.exists(sidecarfile):
|
if os.path.exists(sidecarfile):
|
||||||
logger.info("xmp sidecar file found", extra={"file": sidecarfile})
|
logger.info("xmp sidecar file found", extra={"file": sidecarfile})
|
||||||
try:
|
try:
|
||||||
metadata[item]["tags"] = get_tags(sidecarfile)
|
metadata["images"][item]["tags"] = get_tags(sidecarfile)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.error(e)
|
logger.error(e)
|
||||||
|
|
||||||
image = {
|
image = {
|
||||||
"url": f"{_args.web_root_url}{baseurl}{urllib.parse.quote(item)}",
|
"src": f"{_args.web_root_url}{baseurl}{urllib.parse.quote(item)}",
|
||||||
"thumbnail": f"{_args.web_root_url}.thumbnails/{baseurl}{urllib.parse.quote(item)}.jpg",
|
"msrc": f"{_args.web_root_url}.thumbnails/{baseurl}{urllib.parse.quote(item)}.jpg",
|
||||||
"name": item,
|
"name": item,
|
||||||
"width": metadata[item]["width"],
|
"w": metadata["images"][item]["w"],
|
||||||
"height": metadata[item]["height"],
|
"h": metadata["images"][item]["h"],
|
||||||
"tags": metadata[item]["tags"],
|
"tags": metadata["images"][item]["tags"],
|
||||||
"exifdata": metadata[item].get("exifdata", ""),
|
|
||||||
"xmp": metadata[item].get("xmp", ""),
|
|
||||||
}
|
}
|
||||||
path = os.path.join(_args.root_directory, ".thumbnails", baseurl, item + ".jpg")
|
path = os.path.join(_args.root_directory, ".thumbnails", baseurl, item + ".jpg")
|
||||||
if not os.path.exists(path) or _args.regenerate_thumbnails:
|
if not os.path.exists(path) or _args.regenerate_thumbnails:
|
||||||
@@ -354,10 +376,13 @@ def process_image(item: str, folder: str, _args: Args, baseurl: str, metadata: d
|
|||||||
else:
|
else:
|
||||||
logger.info("raw file found", extra={"file": file, "extension": _raw})
|
logger.info("raw file found", extra={"file": file, "extension": _raw})
|
||||||
image["raw"] = url
|
image["raw"] = url
|
||||||
return image
|
|
||||||
|
metadata["images"][item].update(image)
|
||||||
|
|
||||||
|
return image, metadata
|
||||||
|
|
||||||
|
|
||||||
def generate_html(folder: str, title: str, _args: Args, raw: list[str], version: str, logo) -> None:
|
def generate_html(folder: str, title: str, _args: Args, raw: list[str], version: str, logo) -> list[str]:
|
||||||
"""
|
"""
|
||||||
Generates HTML content for a folder of images.
|
Generates HTML content for a folder of images.
|
||||||
|
|
||||||
@@ -373,15 +398,23 @@ def generate_html(folder: str, title: str, _args: Args, raw: list[str], version:
|
|||||||
logger.info("removing .metadata.json", extra={"folder": folder})
|
logger.info("removing .metadata.json", extra={"folder": folder})
|
||||||
os.remove(os.path.join(folder, ".metadata.json"))
|
os.remove(os.path.join(folder, ".metadata.json"))
|
||||||
metadata = initialize_metadata(folder)
|
metadata = initialize_metadata(folder)
|
||||||
items = sorted(os.listdir(folder))
|
if _args.reverse_sort:
|
||||||
|
items = sorted(os.listdir(folder), reverse=True)
|
||||||
|
else:
|
||||||
|
items = sorted(os.listdir(folder))
|
||||||
|
|
||||||
contains_files = False
|
contains_files = False
|
||||||
images = []
|
images = []
|
||||||
subfolders = []
|
subfolders = []
|
||||||
|
subfoldertags = []
|
||||||
foldername = folder.removeprefix(_args.root_directory)
|
foldername = folder.removeprefix(_args.root_directory)
|
||||||
foldername = f"{foldername}/" if foldername else ""
|
foldername = f"{foldername}/" if foldername else ""
|
||||||
baseurl = urllib.parse.quote(foldername)
|
baseurl = urllib.parse.quote(foldername)
|
||||||
|
|
||||||
|
gone = [item for item in metadata["images"] if item not in items]
|
||||||
|
for gon in gone:
|
||||||
|
del metadata["images"][gon]
|
||||||
|
|
||||||
create_thumbnail_folder(foldername, _args.root_directory)
|
create_thumbnail_folder(foldername, _args.root_directory)
|
||||||
|
|
||||||
logger.info("processing contents", extra={"folder": folder})
|
logger.info("processing contents", extra={"folder": folder})
|
||||||
@@ -389,11 +422,12 @@ def generate_html(folder: str, title: str, _args: Args, raw: list[str], version:
|
|||||||
for item in tqdm(items, total=len(items), desc=f"Getting image infos - {folder}", unit="files", ascii=True, dynamic_ncols=True):
|
for item in tqdm(items, total=len(items), desc=f"Getting image infos - {folder}", unit="files", ascii=True, dynamic_ncols=True):
|
||||||
if item not in EXCLUDES and not item.startswith("."):
|
if item not in EXCLUDES and not item.startswith("."):
|
||||||
if os.path.isdir(os.path.join(folder, item)):
|
if os.path.isdir(os.path.join(folder, item)):
|
||||||
process_subfolder(item, folder, baseurl, subfolders, _args, raw, version, logo)
|
subfoldertags = process_subfolder(item, folder, baseurl, subfolders, _args, raw, version, logo)
|
||||||
else:
|
else:
|
||||||
contains_files = True
|
contains_files = True
|
||||||
if os.path.splitext(item)[1].lower() in _args.file_extensions:
|
if os.path.splitext(item)[1].lower() in _args.file_extensions:
|
||||||
images.append(process_image(item, folder, _args, baseurl, metadata, raw))
|
img, metadata = process_image(item, folder, _args, baseurl, metadata, raw)
|
||||||
|
images.append(img)
|
||||||
if item == "info":
|
if item == "info":
|
||||||
process_info_file(folder, item)
|
process_info_file(folder, item)
|
||||||
if item == "LICENSE":
|
if item == "LICENSE":
|
||||||
@@ -402,24 +436,27 @@ def generate_html(folder: str, title: str, _args: Args, raw: list[str], version:
|
|||||||
for item in items:
|
for item in items:
|
||||||
if item not in EXCLUDES and not item.startswith("."):
|
if item not in EXCLUDES and not item.startswith("."):
|
||||||
if os.path.isdir(os.path.join(folder, item)):
|
if os.path.isdir(os.path.join(folder, item)):
|
||||||
process_subfolder(item, folder, baseurl, subfolders, _args, raw, version, logo)
|
subfoldertags = process_subfolder(item, folder, baseurl, subfolders, _args, raw, version, logo)
|
||||||
else:
|
else:
|
||||||
contains_files = True
|
contains_files = True
|
||||||
if os.path.splitext(item)[1].lower() in _args.file_extensions:
|
if os.path.splitext(item)[1].lower() in _args.file_extensions:
|
||||||
images.append(process_image(item, folder, _args, baseurl, metadata, raw))
|
img, metadata = process_image(item, folder, _args, baseurl, metadata, raw)
|
||||||
|
images.append(img)
|
||||||
if item == "info":
|
if item == "info":
|
||||||
process_info_file(folder, item)
|
process_info_file(folder, item)
|
||||||
if item == "LICENSE":
|
if item == "LICENSE":
|
||||||
process_license(folder, item)
|
process_license(folder, item)
|
||||||
|
|
||||||
|
metadata["subfolders"] = subfolders
|
||||||
update_metadata(metadata, folder)
|
update_metadata(metadata, folder)
|
||||||
|
|
||||||
if should_generate_html(images, contains_files, _args):
|
if should_generate_html(images, contains_files, _args):
|
||||||
create_html_file(folder, title, foldername, images, subfolders, _args, version, logo)
|
subfoldertags = create_html_file(folder, title, foldername, images, subfolders, _args, version, logo, subfoldertags)
|
||||||
else:
|
else:
|
||||||
if os.path.exists(os.path.join(folder, "index.html")):
|
if os.path.exists(os.path.join(folder, "index.html")):
|
||||||
logger.info("removing existing index.html", extra={"folder": folder})
|
logger.info("removing existing index.html", extra={"folder": folder})
|
||||||
os.remove(os.path.join(folder, "index.html"))
|
os.remove(os.path.join(folder, "index.html"))
|
||||||
|
return subfoldertags
|
||||||
|
|
||||||
|
|
||||||
def create_thumbnail_folder(foldername: str, root_directory: str) -> None:
|
def create_thumbnail_folder(foldername: str, root_directory: str) -> None:
|
||||||
@@ -436,7 +473,7 @@ def create_thumbnail_folder(foldername: str, root_directory: str) -> None:
|
|||||||
os.mkdir(thumbnails_path)
|
os.mkdir(thumbnails_path)
|
||||||
|
|
||||||
|
|
||||||
def process_subfolder(item: str, folder: str, baseurl: str, subfolders: list[dict[str, str | None]], _args: Args, raw: list[str], version: str, logo: str) -> None:
|
def process_subfolder(item: str, folder: str, baseurl: str, subfolders: list[dict[str, str | None]], _args: Args, raw: list[str], version: str, logo: str) -> list[str]:
|
||||||
"""
|
"""
|
||||||
Processes a subfolder.
|
Processes a subfolder.
|
||||||
|
|
||||||
@@ -462,10 +499,11 @@ def process_subfolder(item: str, folder: str, baseurl: str, subfolders: list[dic
|
|||||||
else:
|
else:
|
||||||
thumb = f"{_args.web_root_url}.thumbnails/{baseurl}{urllib.parse.quote(item)}/{urllib.parse.quote(thumbitems[0])}.jpg"
|
thumb = f"{_args.web_root_url}.thumbnails/{baseurl}{urllib.parse.quote(item)}/{urllib.parse.quote(thumbitems[0])}.jpg"
|
||||||
|
|
||||||
subfolders.append({"url": subfolder_url, "name": item, "thumb": thumb})
|
subfolders.append({"url": subfolder_url, "name": item, "thumb": thumb, "metadata": f"{_args.web_root_url}{baseurl}{urllib.parse.quote(item)}/.metadata.json"})
|
||||||
if item not in _args.exclude_folders:
|
if item not in _args.exclude_folders:
|
||||||
if not any(fnmatch.fnmatchcase(os.path.join(folder, item), exclude) for exclude in _args.exclude_folders):
|
if not any(fnmatch.fnmatchcase(os.path.join(folder, item), exclude) for exclude in _args.exclude_folders):
|
||||||
generate_html(os.path.join(folder, item), os.path.join(folder, item).removeprefix(_args.root_directory), _args, raw, version, logo)
|
return generate_html(os.path.join(folder, item), os.path.join(folder, item).removeprefix(_args.root_directory), _args, raw, version, logo)
|
||||||
|
return []
|
||||||
|
|
||||||
|
|
||||||
def process_license(folder: str, item: str) -> None:
|
def process_license(folder: str, item: str) -> None:
|
||||||
@@ -510,7 +548,9 @@ def should_generate_html(images: list[dict[str, Any]], contains_files, _args: Ar
|
|||||||
return images or (_args.use_fancy_folders and not contains_files) or (_args.use_fancy_folders and _args.ignore_other_files)
|
return images or (_args.use_fancy_folders and not contains_files) or (_args.use_fancy_folders and _args.ignore_other_files)
|
||||||
|
|
||||||
|
|
||||||
def create_html_file(folder: str, title: str, foldername: str, images: list[dict[str, Any]], subfolders: list[dict[str, str]], _args: Args, version: str, logo: str) -> None:
|
def create_html_file(
|
||||||
|
folder: str, title: str, foldername: str, images: list[dict[str, Any]], subfolders: list[dict[str, str]], _args: Args, version: str, logo: str, subfoldertags: list[str]
|
||||||
|
) -> list[str]:
|
||||||
"""
|
"""
|
||||||
Creates the HTML file using the template.
|
Creates the HTML file using the template.
|
||||||
|
|
||||||
@@ -545,7 +585,7 @@ def create_html_file(folder: str, title: str, foldername: str, images: list[dict
|
|||||||
for img in images:
|
for img in images:
|
||||||
alltags.update(img["tags"])
|
alltags.update(img["tags"])
|
||||||
|
|
||||||
nested_tags = parse_hierarchical_tags(alltags)
|
alltags.update(set(subfoldertags))
|
||||||
|
|
||||||
folder_info = info.get(urllib.parse.quote(folder), "").split("\n")
|
folder_info = info.get(urllib.parse.quote(folder), "").split("\n")
|
||||||
_info = [i for i in folder_info if len(i) > 1] if folder_info else None
|
_info = [i for i in folder_info if len(i) > 1] if folder_info else None
|
||||||
@@ -589,19 +629,28 @@ def create_html_file(folder: str, title: str, foldername: str, images: list[dict
|
|||||||
header=header,
|
header=header,
|
||||||
license=license_info,
|
license=license_info,
|
||||||
subdirectories=subfolders,
|
subdirectories=subfolders,
|
||||||
images=images,
|
|
||||||
info=_info,
|
info=_info,
|
||||||
webmanifest=_args.generate_webmanifest,
|
webmanifest=_args.generate_webmanifest,
|
||||||
version=version,
|
version=version,
|
||||||
logo=logo,
|
logo=logo,
|
||||||
licensefile=license_url,
|
licensefile=license_url,
|
||||||
tags=nested_tags,
|
tags=parse_hierarchical_tags(alltags),
|
||||||
)
|
)
|
||||||
|
|
||||||
with open(html_file, "w", encoding="utf-8") as f:
|
with open(html_file, "w", encoding="utf-8") as f:
|
||||||
logger.info("writing html file", extra={"path": html_file})
|
logger.info("writing html file", extra={"path": html_file})
|
||||||
f.write(content)
|
f.write(content)
|
||||||
|
|
||||||
|
if len(subfoldertags) > 1 and len(alltags) > 1:
|
||||||
|
alltags.update(set(subfoldertags))
|
||||||
|
return sorted(alltags)
|
||||||
|
elif len(subfoldertags) > 1:
|
||||||
|
return sorted(subfoldertags)
|
||||||
|
elif len(alltags) > 1:
|
||||||
|
return sorted(alltags)
|
||||||
|
else:
|
||||||
|
return []
|
||||||
|
|
||||||
|
|
||||||
def list_folder(folder: str, title: str, _args: Args, raw: list[str], version: str, logo: str) -> list[tuple[str, str, str]]:
|
def list_folder(folder: str, title: str, _args: Args, raw: list[str], version: str, logo: str) -> list[tuple[str, str, str]]:
|
||||||
"""
|
"""
|
||||||
|
|||||||
@@ -1,16 +1,16 @@
|
|||||||
{%- macro render_tags(tag_tree, parent) -%}
|
{%- macro render_tags(tag_tree, parent) -%}
|
||||||
<ol>
|
<ol>
|
||||||
{%- for key, value in tag_tree.items() %}
|
{%- for key, value in tag_tree.items() %}
|
||||||
<li class="tagentry">
|
<li class="tagentry">
|
||||||
<label onclick="filter()" title="{{ key }}" id="{{ parent }}|{{ key }}">
|
<label onclick="filter()" title="{{ key }}" id="{{ parent }}|{{ key }}">
|
||||||
<input type="checkbox" />{{ key }}
|
<input class="tag" type="checkbox" />{{ key }}
|
||||||
</label>
|
</label>
|
||||||
{%- if value %}
|
{%- if value %}
|
||||||
{{ render_tags(value, parent + '|' + key) }}
|
{{ render_tags(value, parent + '|' + key) }}
|
||||||
{%- endif %}
|
{%- endif %}
|
||||||
</li>
|
</li>
|
||||||
{%- endfor %}
|
{%- endfor %}
|
||||||
</ol>
|
</ol>
|
||||||
{%- endmacro -%}
|
{%- endmacro -%}
|
||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html lang="en">
|
<html lang="en">
|
||||||
@@ -35,12 +35,10 @@
|
|||||||
<link rel="preload" href="{{ root }}.static/pswp/default-skin/default-skin.css" as="style">
|
<link rel="preload" href="{{ root }}.static/pswp/default-skin/default-skin.css" as="style">
|
||||||
<link rel="modulepreload" href="{{ root }}.static/pswp/photoswipe.min.js">
|
<link rel="modulepreload" href="{{ root }}.static/pswp/photoswipe.min.js">
|
||||||
<link rel="modulepreload" href="{{ root }}.static/pswp/photoswipe-ui-default.min.js">
|
<link rel="modulepreload" href="{{ root }}.static/pswp/photoswipe-ui-default.min.js">
|
||||||
{%- if images %}
|
|
||||||
<link rel="stylesheet" href="{{ root }}.static/pswp/photoswipe.css">
|
<link rel="stylesheet" href="{{ root }}.static/pswp/photoswipe.css">
|
||||||
<link rel="stylesheet" href="{{ root }}.static/pswp/default-skin/default-skin.css">
|
<link rel="stylesheet" href="{{ root }}.static/pswp/default-skin/default-skin.css">
|
||||||
<script src="{{ root }}.static/pswp/photoswipe.min.js"></script>
|
<script src="{{ root }}.static/pswp/photoswipe.min.js"></script>
|
||||||
<script src="{{ root }}.static/pswp/photoswipe-ui-default.min.js"></script>
|
<script src="{{ root }}.static/pswp/photoswipe-ui-default.min.js"></script>
|
||||||
{%- endif %}
|
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
@@ -67,6 +65,11 @@
|
|||||||
<li class="tooltip">
|
<li class="tooltip">
|
||||||
<a>Filter by Tags</a>
|
<a>Filter by Tags</a>
|
||||||
<ol class="tooltiptext tagdropdown" id="tagdropdown">
|
<ol class="tooltiptext tagdropdown" id="tagdropdown">
|
||||||
|
<span class="tagentry">
|
||||||
|
<label onclick="recursive()">
|
||||||
|
<input type="checkbox" id="recursive" />recursive filter
|
||||||
|
</label>
|
||||||
|
</span>
|
||||||
{{ render_tags(tags, '') }}
|
{{ render_tags(tags, '') }}
|
||||||
</ol>
|
</ol>
|
||||||
</li>
|
</li>
|
||||||
@@ -95,11 +98,8 @@
|
|||||||
</div>
|
</div>
|
||||||
{%- endif %}
|
{%- endif %}
|
||||||
</div>
|
</div>
|
||||||
{% if images %}
|
|
||||||
{%- set ns = namespace(count = 0) -%}
|
|
||||||
<div class="row" id="imagelist">
|
<div class="row" id="imagelist">
|
||||||
</div>
|
</div>
|
||||||
{%- endif %}
|
|
||||||
{% if license %}
|
{% if license %}
|
||||||
{%- if 'CC' in license.type %}
|
{%- if 'CC' in license.type %}
|
||||||
<div class="footer" xmlns:cc="http://creativecommons.org/ns#" xmlns:dct="http://purl.org/dc/terms/">
|
<div class="footer" xmlns:cc="http://creativecommons.org/ns#" xmlns:dct="http://purl.org/dc/terms/">
|
||||||
@@ -130,7 +130,6 @@
|
|||||||
<button type="button" onclick="topFunction()" id="totop" title="Back to Top">Back to Top</button>
|
<button type="button" onclick="topFunction()" id="totop" title="Back to Top">Back to Top</button>
|
||||||
</div>
|
</div>
|
||||||
{%- endif %}
|
{%- endif %}
|
||||||
{% if images %}
|
|
||||||
<div class="pswp" tabindex="-1" role="dialog" aria-hidden="true">
|
<div class="pswp" tabindex="-1" role="dialog" aria-hidden="true">
|
||||||
<div class="pswp__bg"></div>
|
<div class="pswp__bg"></div>
|
||||||
<div class="pswp__scroll-wrap">
|
<div class="pswp__scroll-wrap">
|
||||||
@@ -168,29 +167,86 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<script>
|
<script>
|
||||||
var pswpElement = document.querySelectorAll('.pswp')[0];
|
const pswpElement = document.querySelectorAll('.pswp')[0];
|
||||||
var items = [
|
const re = /pid=(\d+)/;
|
||||||
{%- for image in images %}
|
const filterre = /#(.*)/;
|
||||||
{%- if image.exifdata.DateTime %}
|
let items = [];
|
||||||
{ name: "{{ image.name }}", tiff: "{{ image.tiff }}", raw: "{{ image.raw }}", src: "{{ image.url }}", w: {{ image.width }}, h: {{ image.height }}, msrc: "{{ image.thumbnail }}", tags: "{{ image.tags }}", title: "Captured: {{ image.exifdata.DateTime }}" },
|
let shown = [];
|
||||||
{%- else %}
|
let subfolders = [];
|
||||||
{ name: "{{ image.name }}", tiff: "{{ image.tiff }}", raw: "{{ image.raw }}", src: "{{ image.url }}", w: {{ image.width }}, h: {{ image.height }}, msrc: "{{ image.thumbnail }}", tags: "{{ image.tags }}" },
|
let controllers = {};
|
||||||
{%- endif %}
|
let currentFolder = "";
|
||||||
{%- endfor %}
|
|
||||||
];
|
function requestMetadata() {
|
||||||
var re = /pid=(\d+)/;
|
fetch(".metadata.json").then(response => {
|
||||||
var filterre = /#(.*)/;
|
if (!response.ok) {
|
||||||
var controllers = {}
|
throw new Error(`HTTP error! Status: ${response.status}`);
|
||||||
|
}
|
||||||
|
return response.json();
|
||||||
|
})
|
||||||
|
.then(data => {
|
||||||
|
items = Object.values(data.images);
|
||||||
|
subfolders = data.subfolders;
|
||||||
|
if (filterre.test(window.location.href)) {
|
||||||
|
var selected = window.location.href.match(filterre)[1].split(",");
|
||||||
|
setFilter(selected);
|
||||||
|
}
|
||||||
|
filter();
|
||||||
|
|
||||||
|
if (re.test(window.location.href)) {
|
||||||
|
var pid = window.location.href.match(re)[1];
|
||||||
|
openSwipe(parseInt(pid));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (items == []) {
|
||||||
|
document.getElementById("imagelist").style.display = "none"
|
||||||
|
} else {
|
||||||
|
document.getElementById("imagelist").style.display = ""
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch(error => console.error('Failed to fetch data:', error));
|
||||||
|
}
|
||||||
|
|
||||||
function openSwipe(img) {
|
function openSwipe(img) {
|
||||||
var options = {
|
const options = {
|
||||||
index: img
|
index: img
|
||||||
};
|
};
|
||||||
var gallery = new PhotoSwipe(pswpElement, PhotoSwipeUI_Default, shown, options);
|
const gallery = new PhotoSwipe(pswpElement, PhotoSwipeUI_Default, shown, options);
|
||||||
gallery.init();
|
gallery.init();
|
||||||
}
|
}
|
||||||
|
|
||||||
let totopbutton = document.getElementById("totop");
|
async function recursive(sub = undefined) {
|
||||||
|
const ischecked = document.getElementById("recursive").checked;
|
||||||
|
const folders = document.getElementsByClassName("folders")[0];
|
||||||
|
if (sub == undefined) {
|
||||||
|
sub = subfolders;
|
||||||
|
}
|
||||||
|
if (ischecked) {
|
||||||
|
if (folders != undefined) {
|
||||||
|
folders.style.display = "none";
|
||||||
|
}
|
||||||
|
for (const folder of sub) {
|
||||||
|
currentFolder = folder.name;
|
||||||
|
try {
|
||||||
|
const response = await fetch(folder.metadata);
|
||||||
|
const data = await response.json();
|
||||||
|
if (data.subfolders.length > 0) {
|
||||||
|
await recursive(data.subfolders);
|
||||||
|
}
|
||||||
|
items = items.concat(Object.values(data.images));
|
||||||
|
filter();
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Failed to fetch folder metadata:', error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (folders != undefined) {
|
||||||
|
folders.style.display = "";
|
||||||
|
}
|
||||||
|
requestMetadata();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const totopbutton = document.getElementById("totop");
|
||||||
|
|
||||||
window.onscroll = function () { scrollFunction() };
|
window.onscroll = function () { scrollFunction() };
|
||||||
|
|
||||||
@@ -206,15 +262,15 @@
|
|||||||
window.scrollTo({ top: 0, behavior: 'smooth' })
|
window.scrollTo({ top: 0, behavior: 'smooth' })
|
||||||
}
|
}
|
||||||
|
|
||||||
function updateImageList(images) {
|
function updateImageList() {
|
||||||
var str = ""
|
let str = ""
|
||||||
var imagelist = document.getElementById("imagelist");
|
let imagelist = document.getElementById("imagelist");
|
||||||
images.forEach((item, index) => {
|
shown.forEach((item, index) => {
|
||||||
str += '<div class="column"><figure><img src="' + item.msrc + '" onclick="openSwipe(' + index + ')" onmouseover="prefetch(' + index + ')" onmouseleave="cancel(' + index + ')" /><figcaption class="caption">' + item.name;
|
str += '<div class="column"><figure><img src="' + item.msrc + '" onclick="openSwipe(' + index + ')" onmouseover="prefetch(' + index + ')" onmouseleave="cancel(' + index + ')" /><figcaption class="caption">' + item.name;
|
||||||
if (item.tiff != "") {
|
if (item.tiff != "" & item.tiff != undefined) {
|
||||||
str += ' <a href="' + item.tiff + '">TIFF</a>';
|
str += ' <a href="' + item.tiff + '">TIFF</a>';
|
||||||
}
|
}
|
||||||
if (item.raw != "") {
|
if (item.raw != "" & item.raw != undefined) {
|
||||||
str += ' <a href="' + item.raw + '">RAW</a>';
|
str += ' <a href="' + item.raw + '">RAW</a>';
|
||||||
}
|
}
|
||||||
str += '</figcaption></figure></div>';
|
str += '</figcaption></figure></div>';
|
||||||
@@ -241,33 +297,38 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
function filter() {
|
function filter() {
|
||||||
|
shown = [];
|
||||||
|
|
||||||
window.location.href = window.location.href.split("#")[0] + "#";
|
window.location.href = window.location.href.split("#")[0] + "#";
|
||||||
|
|
||||||
const selected_tags = [];
|
const selected_tags = [];
|
||||||
const shown = [];
|
const tagcheckboxes = document.querySelectorAll("#tagdropdown input[class='tag']:checked");
|
||||||
|
|
||||||
const tagcheckboxes = document.querySelectorAll("#tagdropdown input[type='checkbox']:checked");
|
|
||||||
|
|
||||||
tagcheckboxes.forEach((checkbox) => {
|
tagcheckboxes.forEach((checkbox) => {
|
||||||
const tag = checkbox.parentElement.id.trim().substring(1);
|
const tag = checkbox.parentElement.id.trim().substring(1);
|
||||||
selected_tags.push(tag);
|
selected_tags.push(tag);
|
||||||
});
|
});
|
||||||
console.log(selected_tags);
|
|
||||||
|
|
||||||
const urltags = selected_tags.join(",");
|
const urltags = selected_tags.join(",");
|
||||||
|
|
||||||
items.forEach((item) => {
|
const isRecursiveChecked = document.getElementById("recursive").checked;
|
||||||
const tags = item.tags || [];
|
|
||||||
const include = selected_tags.every(tag => tags.includes(tag));
|
|
||||||
if (include || selected_tags.length === 0) {
|
|
||||||
shown.push(item);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
updateImageList(shown);
|
for (const item of items) {
|
||||||
|
const tags = item.tags || [];
|
||||||
|
const include = selected_tags.every(tag => tags.some(t => t.startsWith(tag)));
|
||||||
|
|
||||||
|
if (include || selected_tags.length === 0) {
|
||||||
|
if (isRecursiveChecked || item.folder === currentFolder) {
|
||||||
|
shown.push(item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
updateImageList();
|
||||||
window.location.href += urltags;
|
window.location.href += urltags;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
function setFilter(selected) {
|
function setFilter(selected) {
|
||||||
tagdropdown = document.getElementById("tagdropdown").getElementsByTagName("li");
|
tagdropdown = document.getElementById("tagdropdown").getElementsByTagName("li");
|
||||||
selected.forEach((tag) => {
|
selected.forEach((tag) => {
|
||||||
@@ -280,20 +341,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
function onLoad() {
|
function onLoad() {
|
||||||
{%- if tags | length > 0 %}
|
requestMetadata();
|
||||||
if (filterre.test(window.location.href)) {
|
|
||||||
var selected = window.location.href.match(filterre)[1].split(",");
|
|
||||||
setFilter(selected);
|
|
||||||
}
|
|
||||||
filter();
|
|
||||||
{%- else %}
|
|
||||||
updateImageList(items);
|
|
||||||
{%- endif %}
|
|
||||||
|
|
||||||
if (re.test(window.location.href)) {
|
|
||||||
var pid = window.location.href.match(re)[1];
|
|
||||||
openSwipe(parseInt(pid));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
window.addEventListener ?
|
window.addEventListener ?
|
||||||
@@ -301,7 +349,6 @@
|
|||||||
window.attachEvent && window.attachEvent("onload", onLoad);
|
window.attachEvent && window.attachEvent("onload", onLoad);
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
{%- endif %}
|
|
||||||
</body>
|
</body>
|
||||||
|
|
||||||
</html>
|
</html>
|
||||||
|
Before Width: | Height: | Size: 3.5 MiB After Width: | Height: | Size: 3.5 MiB |
|
Before Width: | Height: | Size: 7.3 MiB After Width: | Height: | Size: 7.3 MiB |
Reference in New Issue
Block a user