diff --git a/.gitignore b/.gitignore index cd0a4fb..dd74b13 100644 --- a/.gitignore +++ b/.gitignore @@ -164,7 +164,7 @@ cython_debug/ test/.static test/.thumbnails test/**/index.html -test/**/.sizelist.json +test/**/.metadata.json test/manifest.json themes/previews logs diff --git a/.version b/.version index d5724cd..9aa3464 100644 --- a/.version +++ b/.version @@ -1 +1 @@ -2.6.2 \ No newline at end of file +2.7.0 \ No newline at end of file diff --git a/README.md b/README.md index a2e4897..2e52fc1 100644 --- a/README.md +++ b/README.md @@ -97,6 +97,7 @@ To generate a web manifest file: - The script generates the preview thumbnails in a `.thumbnails` subdirectory within the root folder. - The `.lock` file prevents multiple instances of the script from running simultaneously. Make sure to remove it if the script terminates unexpectedly. - Add a `info` file into any directory containing pictures and it will be read and displayed as a tooltip on the website. +- Add tags to the Image exif or to `.metadata.json` to tag images for filtering. ## License diff --git a/StaticGalleryBuilder.code-workspace b/StaticGalleryBuilder.code-workspace index 49991db..6c9d414 100644 --- a/StaticGalleryBuilder.code-workspace +++ b/StaticGalleryBuilder.code-workspace @@ -77,7 +77,7 @@ { "args": [ "${workspaceFolder}/themes", - "https://pictures.sorogon.eu/Analog/Example/" + "https://pictures.sorogon.eu/public/Example/" ], "console": "integratedTerminal", "name": "Generate Themes previews", diff --git a/files/global.css b/files/global.css index 55dc205..0376120 100644 --- a/files/global.css +++ b/files/global.css @@ -131,14 +131,18 @@ figure { text-decoration: none; } -.navbar .title { +.navbar .navleft { + float: left; +} + +.navbar .navcenter { position: absolute; left: 50%; transform: translateX(-50%); } -.navbar .license { - float: right; +.navbar .navright { + float: right } .navbar li .header { @@ -150,18 +154,28 @@ figure { .tooltip { position: relative; + cursor: pointer; } .tooltip .tooltiptext { display: none; + cursor: default; width: max-content; position: absolute; z-index: 100; opacity: 0; transition: opacity 0.3s; + float: left; +} + +.tooltip .infotext { padding: 12px; } +.tooltip .tagdropdown { + padding: 0; +} + .tooltip:hover .tooltiptext { display: block; opacity: 1; @@ -172,6 +186,22 @@ figure { opacity: 1; } +.tooltip .tooltiptext .tagentry { + list-style: none; + width: 100%; + cursor: pointer; + margin: 0; + padding: 0; +} + +.tooltip .tooltiptext .tagentry label { + cursor: pointer; + width: 100%; + height: 100%; + padding: 12px; + display: block; +} + .column { -ms-flex: 12.5%; flex: 12.5%; diff --git a/generate_previews.py b/generate_previews.py index 87c4e9b..0a89f59 100644 --- a/generate_previews.py +++ b/generate_previews.py @@ -1,7 +1,6 @@ import os import re import sys -import time import shutil import base64 import fileinput diff --git a/modules/generate_html.py b/modules/generate_html.py index de6102b..2a8925d 100644 --- a/modules/generate_html.py +++ b/modules/generate_html.py @@ -7,7 +7,7 @@ from typing import Any from datetime import datetime from tqdm.auto import tqdm -from PIL import Image, ExifTags, TiffImagePlugin +from PIL import Image, ExifTags, TiffImagePlugin, UnidentifiedImageError from jinja2 import Environment, FileSystemLoader from modules.logger import logger @@ -29,54 +29,60 @@ Image.MAX_IMAGE_PIXELS = 933120000 # Initialize Jinja2 environment for template rendering env = Environment(loader=FileSystemLoader(os.path.join(SCRIPTDIR, "templates"))) -thumbnails: list[tuple[str, str]] = [] +thumbnails: list[tuple[str, str, str]] = [] info: dict[str, str] = {} licens: dict[str, str] = {} -def initialize_sizelist(folder: str) -> dict[str, dict[str, int]]: +def initialize_metadata(folder: str) -> dict[str, dict[str, int]]: """ - Initializes the size list JSON file if it doesn't exist. + Initializes the metadata JSON file if it doesn't exist. Args: - folder (str): The folder in which the size list file is located. + folder (str): The folder in which the metadata file is located. Returns: - dict[str, dict[str, int]]: The size list dictionary. + dict[str, dict[str, int]]: The metadata dictionary. """ - sizelist = {} - sizelist_path = os.path.join(folder, ".sizelist.json") - if not os.path.exists(sizelist_path): - logger.info("creating new size list file", extra={"file": sizelist_path}) - with open(sizelist_path, "x", encoding="utf-8") as sizelistfile: - sizelistfile.write("{}") - with open(sizelist_path, "r+", encoding="utf-8") as sizelistfile: - logger.info("reading size list file", extra={"file": sizelist_path}) + metadata = {} + metadata_path = os.path.join(folder, ".metadata.json") + if not os.path.exists(metadata_path): + logger.info("creating new metadata file", extra={"file": metadata_path}) + with open(metadata_path, "x", encoding="utf-8") as metadatafile: + metadatafile.write("{}") + with open(metadata_path, "r+", encoding="utf-8") as metadatafile: + logger.info("reading metadata file", extra={"file": metadata_path}) try: - sizelist = json.loads(sizelistfile.read()) + metadata = json.loads(metadatafile.read()) except json.decoder.JSONDecodeError: - logger.warning("invalid JSON in size list file", extra={"file": sizelist_path}) - sizelist = {} - return sizelist + logger.warning("invalid JSON in metadata file", extra={"file": metadata_path}) + metadata = {} + + # remove old sizelist if it exists + sizelist_path = os.path.join(folder, ".sizelist.json") + if os.path.exists(sizelist_path): + logger.warning("found old .sizelist.json, removing it...", extra={"path": sizelist_path}) + os.remove(sizelist_path) + return metadata -def update_sizelist(sizelist: dict[str, dict[str, Any]], folder: str) -> None: +def update_metadata(metadata: dict[str, dict[str, Any]], folder: str) -> None: """ - Updates the size list JSON file. + Updates the metadata JSON file. Args: - sizelist (dict[str, dict[str, int]]): The size list dictionary to be written to the file. - folder (str): The folder in which the size list file is located. + metadata (dict[str, dict[str, int]]): The metadata dictionary to be written to the file. + folder (str): The folder in which the metadata file is located. """ - sizelist_path = os.path.join(folder, ".sizelist.json") - if sizelist: - with open(sizelist_path, "w", encoding="utf-8") as sizelistfile: - logger.info("writing size list file", extra={"file": sizelist_path}) - sizelistfile.write(json.dumps(sizelist, indent=4)) + metadata_path = os.path.join(folder, ".metadata.json") + if metadata: + with open(metadata_path, "w", encoding="utf-8") as metadatafile: + logger.info("writing metadata file", extra={"file": metadata_path}) + metadatafile.write(json.dumps(metadata, indent=4)) else: - if os.path.exists(sizelist_path): - logger.info("deleting empty size list file", extra={"file": sizelist_path}) - os.remove(sizelist_path) + if os.path.exists(metadata_path): + logger.info("deleting empty metadata file", extra={"file": metadata_path}) + os.remove(metadata_path) def get_image_info(item: str, folder: str) -> dict[str, Any]: @@ -91,10 +97,15 @@ def get_image_info(item: str, folder: str) -> dict[str, Any]: dict[str, Any]: A dictionary containing image width, height, and EXIF data. """ file = os.path.join(folder, item) - with Image.open(file) as img: - logger.info("extracting image information", extra={"file": file}) - exif = img.getexif() - width, height = img.size + try: + with Image.open(file) as img: + logger.info("extracting image information", extra={"file": file}) + exif = img.getexif() + width, height = img.size + except UnidentifiedImageError: + logger.error("cannot identify image file", extra={"file": file}) + print(f"cannot identify image file: {file}") + return {"width": None, "height": None, "tags": None, "exifdata": None} if exif: logger.info("extracting EXIF data", extra={"file": file}) ifd = exif.get_ifd(ExifTags.IFD.Exif) @@ -116,9 +127,9 @@ def get_image_info(item: str, folder: str) -> dict[str, Any]: content = newtuple if tag in ["DateTime", "DateTimeOriginal", "DateTimeDigitized"]: epr = r"\d{4}:\d{2}:\d{2} \d{2}:\d{2}:\d{2}" - if re.match(epr, content): + if re.match(epr, str(content)): try: - content = datetime.strptime(content, "%Y:%m:%d %H:%M:%S").strftime("%Y-%m-%d %H:%M:%S") + content = datetime.strptime(str(content), "%Y:%m:%d %H:%M:%S").strftime("%Y-%m-%d %H:%M:%S") except ValueError: content = None else: @@ -130,12 +141,12 @@ def get_image_info(item: str, folder: str) -> dict[str, Any]: for key in ["PrintImageMatching", "UserComment", "MakerNote"]: if key in exifdata: del exifdata[key] - return {"width": width, "height": height, "exifdata": exifdata} + return {"width": width, "height": height, "tags": [], "exifdata": exifdata} else: - return {"width": width, "height": height, "exifdata": None} + return {"width": width, "height": height, "tags": [], "exifdata": None} -def process_image(item: str, folder: str, _args: Args, baseurl: str, sizelist: dict[str, dict[str, int]], raw: list[str]) -> dict[str, Any]: +def process_image(item: str, folder: str, _args: Args, baseurl: str, metadata: dict[str, dict[str, int]], raw: list[str]) -> dict[str, Any]: """ Processes an image and prepares its data for the HTML template. @@ -144,23 +155,24 @@ def process_image(item: str, folder: str, _args: Args, baseurl: str, sizelist: d folder (str): The folder containing the image. _args (Args): Parsed command line arguments. baseurl (str): Base URL for the web root. - sizelist (dict[str, dict[str, int]]): dictionary containing size information for images. + metadata (dict[str, dict[str, int]]): dictionary containing size information for images. raw (list[str]): list of raw image file extensions. Returns: dict[str, Any]: dictionary containing image details for HTML rendering. """ extsplit = os.path.splitext(item) - if item not in sizelist or _args.reread_metadata: - sizelist[item] = get_image_info(item, folder) + if item not in metadata or _args.reread_metadata: + metadata[item] = get_image_info(item, folder) image = { "url": f"{_args.web_root_url}{baseurl}{urllib.parse.quote(item)}", "thumbnail": f"{_args.web_root_url}.thumbnails/{baseurl}{urllib.parse.quote(item)}.jpg", "name": item, - "width": sizelist[item]["width"], - "height": sizelist[item]["height"], - "exifdata": sizelist[item].get("exifdata", ""), + "width": metadata[item]["width"], + "height": metadata[item]["height"], + "tags": metadata[item]["tags"], + "exifdata": metadata[item].get("exifdata", ""), } path = os.path.join(_args.root_directory, ".thumbnails", baseurl, item + ".jpg") if not os.path.exists(path) or _args.regenerate_thumbnails: @@ -193,10 +205,10 @@ def generate_html(folder: str, title: str, _args: Args, raw: list[str], version: """ logger.info("processing folder", extra={"folder": folder}) if _args.regenerate_thumbnails: - if os.path.exists(os.path.join(folder, ".sizelist.json")): - logger.info("removing .sizelist.json", extra={"folder": folder}) - os.remove(os.path.join(folder, ".sizelist.json")) - sizelist = initialize_sizelist(folder) + if os.path.exists(os.path.join(folder, ".metadata.json")): + logger.info("removing .metadata.json", extra={"folder": folder}) + os.remove(os.path.join(folder, ".metadata.json")) + metadata = initialize_metadata(folder) items = sorted(os.listdir(folder)) contains_files = False @@ -217,7 +229,7 @@ def generate_html(folder: str, title: str, _args: Args, raw: list[str], version: else: contains_files = True if os.path.splitext(item)[1].lower() in _args.file_extensions: - images.append(process_image(item, folder, _args, baseurl, sizelist, raw)) + images.append(process_image(item, folder, _args, baseurl, metadata, raw)) if item == "info": process_info_file(folder, item) if item == "LICENSE": @@ -230,13 +242,13 @@ def generate_html(folder: str, title: str, _args: Args, raw: list[str], version: else: contains_files = True if os.path.splitext(item)[1].lower() in _args.file_extensions: - images.append(process_image(item, folder, _args, baseurl, sizelist, raw)) + images.append(process_image(item, folder, _args, baseurl, metadata, raw)) if item == "info": process_info_file(folder, item) if item == "LICENSE": process_license(folder, item) - update_sizelist(sizelist, folder) + update_metadata(metadata, folder) if should_generate_html(images, contains_files, _args): create_html_file(folder, title, foldername, images, subfolders, _args, version, logo) @@ -260,7 +272,7 @@ def create_thumbnail_folder(foldername: str, root_directory: str) -> None: os.mkdir(thumbnails_path) -def process_subfolder(item: str, folder: str, baseurl: str, subfolders: list[dict[str, str]], _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) -> None: """ Processes a subfolder. @@ -365,6 +377,12 @@ def create_html_file(folder: str, title: str, foldername: str, images: list[dict else None ) + alltags = set() + for img in images: + for tag in img["tags"]: + alltags.add(tag) + alltags = sorted(alltags) + 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 if _args.reverse_sort: @@ -413,6 +431,7 @@ def create_html_file(folder: str, title: str, foldername: str, images: list[dict version=version, logo=logo, licensefile=license_url, + tags=alltags, ) with open(html_file, "w", encoding="utf-8") as f: @@ -420,7 +439,7 @@ def create_html_file(folder: str, title: str, foldername: str, images: list[dict f.write(content) -def list_folder(folder: str, title: str, _args: Args, raw: list[str], version: str, logo: str) -> list[tuple[str, str]]: +def list_folder(folder: str, title: str, _args: Args, raw: list[str], version: str, logo: str) -> list[tuple[str, str, str]]: """ lists and processes a folder, generating HTML files. diff --git a/templates/default.css b/templates/default.css index 4cf2d7d..5f650be 100644 --- a/templates/default.css +++ b/templates/default.css @@ -52,6 +52,10 @@ background-color: var(--color2); } +.tagentry:hover { + background-color: var(--color4); +} + .column img { background-color: var(--color2); } diff --git a/templates/index.html.j2 b/templates/index.html.j2 index 8a45517..fb43591 100644 --- a/templates/index.html.j2 +++ b/templates/index.html.j2 @@ -31,23 +31,38 @@
- + {% if subdirectories %} {%- for subdirectory in subdirectories %} @@ -69,7 +84,7 @@
{% if images %} {%- set ns = namespace(count = 0) -%} -
+
{%- for image in images %}
@@ -160,9 +175,9 @@ var items = [ {%- for image in images %} {%- if image.exifdata.DateTime %} - { src: "{{ image.url }}", w: {{ image.width }}, h: {{ image.height }}, msrc: "{{ image.thumbnail }}", title: "Captured: {{ image.exifdata.DateTime }}" }, + { src: "{{ image.url }}", w: {{ image.width }}, h: {{ image.height }}, msrc: "{{ image.thumbnail }}", tags: "{{ image.tags }}", title: "Captured: {{ image.exifdata.DateTime }}" }, {%- else %} - { src: "{{ image.url }}", w: {{ image.width }}, h: {{ image.height }}, msrc: "{{ image.thumbnail }}" }, + { src: "{{ image.url }}", w: {{ image.width }}, h: {{ image.height }}, msrc: "{{ image.thumbnail }}", tags: "{{ image.tags }}" }, {%- endif %} {%- endfor %} ]; @@ -207,13 +222,42 @@ fetch(urlToFetch, { method: 'get', signal: signal, - }).catch(function (err) {}); + }).catch(function (err) { }); } function cancel(img) { controllers[img].abort(); delete controllers[img]; } + + {%- if tags|length > 0 %} + function filter() { + var selected_tags = []; + var tagdropdown, imagelist, figures, i, j, tags, incl; + tagdropdown = document.getElementById("tagdropdown").getElementsByTagName("li"); + for (i = 0; i < tagdropdown.length; i++) { + if (tagdropdown[i].firstChild.firstChild.checked) { + selected_tags.push([tagdropdown[i].innerText]) + } + } + imagelist = document.getElementById("imagelist"); + figures = imagelist.getElementsByTagName("div"); + for (i = 0; i < figures.length; i++) { + tags = items[i].tags; + incl = true; + for (j = 0; j < selected_tags.length; j++) { + if (tags.indexOf(selected_tags[j]) == -1) { + incl = false; + } + } + if (incl || selected_tags == []) { + figures[i].style.display = ""; + } else { + figures[i].style.display = "none"; + } + } + } + {%- endif %} {%- endif %} diff --git a/test/example/license.html b/test/example/license.html index 60ece31..d60db59 100644 --- a/test/example/license.html +++ b/test/example/license.html @@ -6,18 +6,18 @@ example - LICENSE - - - - - + + + + +
@@ -453,14 +453,14 @@ Creative Commons may be contacted at creativecommons.org.
diff --git a/themes/alpenglow-dark.css b/themes/alpenglow-dark.css index 0be6576..df5b057 100644 --- a/themes/alpenglow-dark.css +++ b/themes/alpenglow-dark.css @@ -97,6 +97,10 @@ body { background-color: var(--color6); } +.tagentry:hover { + background-color: var(--color3); +} + .column img { background-color: var(--bcolor2); } diff --git a/themes/alpenglow.css b/themes/alpenglow.css index 48f9556..a35b69b 100644 --- a/themes/alpenglow.css +++ b/themes/alpenglow.css @@ -96,6 +96,10 @@ body { background-color: var(--color3); } +.tagentry:hover { + background-color: var(--color7); +} + .column img { background-color: var(--bcolor1); } diff --git a/themes/aritim-dark.css b/themes/aritim-dark.css index 3fb8803..b5f55a9 100644 --- a/themes/aritim-dark.css +++ b/themes/aritim-dark.css @@ -74,6 +74,10 @@ background-color: var(--bcolor1); } +.tagentry:hover { + background-color: var(--bcolor3); +} + .column img { background-color: var(--bcolor1); } diff --git a/themes/aritim.css b/themes/aritim.css index b5348b4..0e53073 100644 --- a/themes/aritim.css +++ b/themes/aritim.css @@ -74,6 +74,10 @@ background-color: var(--bcolor1); } +.tagentry:hover { + background-color: var(--bcolor3); +} + .column img { background-color: var(--bcolor1); } diff --git a/themes/autumn.css b/themes/autumn.css index fb71ab5..62f21f6 100644 --- a/themes/autumn.css +++ b/themes/autumn.css @@ -79,6 +79,10 @@ font-family: "Playfair Display", serif; } +.tagentry:hover { + background-color: var(--color3); +} + .column img { background-color: var(--bcolor4); } diff --git a/themes/carnation.css b/themes/carnation.css index f115e7f..8739d30 100644 --- a/themes/carnation.css +++ b/themes/carnation.css @@ -73,6 +73,10 @@ background-color: var(--bcolor2); } +.tagentry:hover { + background-color: var(--bcolor4); +} + .column img { background-color: var(--bcolor4); } diff --git a/themes/catpuccin.css b/themes/catpuccin.css index 6ad9f80..423c84a 100644 --- a/themes/catpuccin.css +++ b/themes/catpuccin.css @@ -79,6 +79,10 @@ font-family: "Nunito", sans-serif; } +.tagentry:hover { + background-color: var(--color4); +} + .column img { background-color: var(--bcolor4); } diff --git a/themes/cornflower.css b/themes/cornflower.css index b4ed888..e25936d 100644 --- a/themes/cornflower.css +++ b/themes/cornflower.css @@ -73,6 +73,10 @@ background-color: var(--bcolor2); } +.tagentry:hover { + background-color: var(--bcolor4); +} + .column img { background-color: var(--bcolor4); } diff --git a/themes/default-dark.css b/themes/default-dark.css index b7c51a3..f4235a3 100644 --- a/themes/default-dark.css +++ b/themes/default-dark.css @@ -52,6 +52,10 @@ background-color: var(--color3); } +.tagentry:hover { + background-color: var(--color4); +} + .column img { background-color: var(--bcolor2); } diff --git a/themes/default.css b/themes/default.css index c344e04..9d8b1e2 100644 --- a/themes/default.css +++ b/themes/default.css @@ -52,6 +52,10 @@ background-color: var(--color2); } +.tagentry:hover { + background-color: var(--color4); +} + .column img { background-color: var(--color2); } diff --git a/themes/ivy.css b/themes/ivy.css index 2a29d83..b053ba0 100644 --- a/themes/ivy.css +++ b/themes/ivy.css @@ -73,6 +73,10 @@ background-color: var(--bcolor2); } +.tagentry:hover { + background-color: var(--bcolor4); +} + .column img { background-color: var(--bcolor4); } diff --git a/themes/kjoe.css b/themes/kjoe.css index eb5bcd6..221a6e5 100644 --- a/themes/kjoe.css +++ b/themes/kjoe.css @@ -72,6 +72,10 @@ background-color: var(--color3); } +.tagentry:hover { + background-color: var(--color2); +} + .column img { background-color: var(--bcolor3); } diff --git a/themes/monokai-vibrant.css b/themes/monokai-vibrant.css index 2c36735..4982e0b 100644 --- a/themes/monokai-vibrant.css +++ b/themes/monokai-vibrant.css @@ -55,6 +55,10 @@ background-color: var(--bcolor2); } +.tagentry:hover { + background-color: var(--bcolor3); +} + .column img { background-color: var(--bcolor5); } diff --git a/themes/rainbow.css b/themes/rainbow.css index 1e6559d..5f53b52 100644 --- a/themes/rainbow.css +++ b/themes/rainbow.css @@ -76,6 +76,10 @@ background-color: var(--bcolor2); } +.tagentry:hover { + background-color: var(--bcolor4); +} + .column img { background-color: var(--bcolor5); } diff --git a/themes/screenshots/alpenglow-dark.png b/themes/screenshots/alpenglow-dark.png index 0099cff..c848fa5 100644 Binary files a/themes/screenshots/alpenglow-dark.png and b/themes/screenshots/alpenglow-dark.png differ diff --git a/themes/screenshots/alpenglow.png b/themes/screenshots/alpenglow.png index 51d0126..122d3c6 100644 Binary files a/themes/screenshots/alpenglow.png and b/themes/screenshots/alpenglow.png differ diff --git a/themes/screenshots/aritim-dark.png b/themes/screenshots/aritim-dark.png index 8f4eb8a..be6123e 100644 Binary files a/themes/screenshots/aritim-dark.png and b/themes/screenshots/aritim-dark.png differ diff --git a/themes/screenshots/aritim.png b/themes/screenshots/aritim.png index aee86f1..0051e93 100644 Binary files a/themes/screenshots/aritim.png and b/themes/screenshots/aritim.png differ diff --git a/themes/screenshots/autumn.png b/themes/screenshots/autumn.png index ca1bbe1..456427c 100644 Binary files a/themes/screenshots/autumn.png and b/themes/screenshots/autumn.png differ diff --git a/themes/screenshots/carnation.png b/themes/screenshots/carnation.png index a964fe9..c6fac3c 100644 Binary files a/themes/screenshots/carnation.png and b/themes/screenshots/carnation.png differ diff --git a/themes/screenshots/catpuccin.png b/themes/screenshots/catpuccin.png index 62e1ff4..c9de6f9 100644 Binary files a/themes/screenshots/catpuccin.png and b/themes/screenshots/catpuccin.png differ diff --git a/themes/screenshots/cornflower.png b/themes/screenshots/cornflower.png index d3c85a3..c89d912 100644 Binary files a/themes/screenshots/cornflower.png and b/themes/screenshots/cornflower.png differ diff --git a/themes/screenshots/default-dark.png b/themes/screenshots/default-dark.png index 7cb1841..0a72b2c 100644 Binary files a/themes/screenshots/default-dark.png and b/themes/screenshots/default-dark.png differ diff --git a/themes/screenshots/default.png b/themes/screenshots/default.png index abfe791..630118b 100644 Binary files a/themes/screenshots/default.png and b/themes/screenshots/default.png differ diff --git a/themes/screenshots/ivy.png b/themes/screenshots/ivy.png index 817f5c6..6244cd4 100644 Binary files a/themes/screenshots/ivy.png and b/themes/screenshots/ivy.png differ diff --git a/themes/screenshots/kjoe.png b/themes/screenshots/kjoe.png index 6dbc1ce..17a8d4b 100644 Binary files a/themes/screenshots/kjoe.png and b/themes/screenshots/kjoe.png differ diff --git a/themes/screenshots/monokai-vibrant.png b/themes/screenshots/monokai-vibrant.png index fc2a921..af8e943 100644 Binary files a/themes/screenshots/monokai-vibrant.png and b/themes/screenshots/monokai-vibrant.png differ diff --git a/themes/screenshots/rainbow.png b/themes/screenshots/rainbow.png index ce6b1d4..562a49f 100644 Binary files a/themes/screenshots/rainbow.png and b/themes/screenshots/rainbow.png differ diff --git a/themes/screenshots/spring.png b/themes/screenshots/spring.png index c497eee..b4fb1e4 100644 Binary files a/themes/screenshots/spring.png and b/themes/screenshots/spring.png differ diff --git a/themes/screenshots/steam.png b/themes/screenshots/steam.png index 2112848..4b0895f 100644 Binary files a/themes/screenshots/steam.png and b/themes/screenshots/steam.png differ diff --git a/themes/screenshots/summer.png b/themes/screenshots/summer.png index 172a2f1..2bff30c 100644 Binary files a/themes/screenshots/summer.png and b/themes/screenshots/summer.png differ diff --git a/themes/screenshots/sunflower.png b/themes/screenshots/sunflower.png index 78008ae..cc97981 100644 Binary files a/themes/screenshots/sunflower.png and b/themes/screenshots/sunflower.png differ diff --git a/themes/screenshots/winter.png b/themes/screenshots/winter.png index 6e8652b..4c7df27 100644 Binary files a/themes/screenshots/winter.png and b/themes/screenshots/winter.png differ diff --git a/themes/spring.css b/themes/spring.css index dd6eb9f..ef623ae 100644 --- a/themes/spring.css +++ b/themes/spring.css @@ -79,6 +79,10 @@ font-family: "Lora", serif; } +.tagentry:hover { + background-color: var(--bcolor3); +} + .column img { background-color: var(--bcolor4); } diff --git a/themes/steam.css b/themes/steam.css index 08c5059..20b14cb 100644 --- a/themes/steam.css +++ b/themes/steam.css @@ -80,6 +80,10 @@ background-color: var(--color4); } +.tagentry:hover { + background-color: var(--color3); +} + .column img { background-color: var(--color4); } diff --git a/themes/summer.css b/themes/summer.css index c0bd549..2b10662 100644 --- a/themes/summer.css +++ b/themes/summer.css @@ -80,6 +80,11 @@ font-family: "Roboto", sans-serif; } +.tagentry:hover { + background-color: var(--bcolor3); + color: var(--bcolor2); +} + .column img { background-color: var(--bcolor4); } diff --git a/themes/sunflower.css b/themes/sunflower.css index 8bb0f2f..0b40435 100644 --- a/themes/sunflower.css +++ b/themes/sunflower.css @@ -74,6 +74,10 @@ background-color: var(--bcolor2); } +.tagentry:hover { + background-color: var(--bcolor4); +} + .column img { background-color: var(--bcolor4); } diff --git a/themes/winter.css b/themes/winter.css index 6776b41..42c58b4 100644 --- a/themes/winter.css +++ b/themes/winter.css @@ -88,6 +88,10 @@ font-family: "Montserrat", sans-serif; } +.tagentry:hover { + background-color: var(--color2); +} + .column img { background-color: var(--bcolor4); }