Compare commits
20 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
79e34d7e43
|
|||
|
0cda1706fa
|
|||
|
85467f4f1e
|
|||
|
00ccb96581
|
|||
|
5227beb02a
|
|||
|
22f9cb4e00
|
|||
|
dbf3e5c27a
|
|||
|
d9ca40bf77
|
|||
|
b8cbc49647
|
|||
|
b80e98a4ec
|
|||
|
350f41f439
|
|||
|
00b5020642
|
|||
|
492ea8755f
|
|||
|
39da474db6
|
|||
|
44bcd5607f
|
|||
|
5ff44a1912
|
|||
|
4241f3965a
|
|||
|
002e9c62db
|
|||
| cf494401c8 | |||
|
2a0323e579
|
3
.gitignore
vendored
@@ -164,7 +164,8 @@ cython_debug/
|
||||
test/.static
|
||||
test/.thumbnails
|
||||
test/**/index.html
|
||||
test/**/.sizelist.json
|
||||
test/**/license.html
|
||||
test/**/.metadata.json
|
||||
test/manifest.json
|
||||
themes/previews
|
||||
logs
|
||||
|
||||
@@ -1 +1 @@
|
||||
3.12
|
||||
StaticGalleryBuilder
|
||||
|
||||
@@ -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 xmp `subject` or to `.metadata.json` to tag images for filtering.
|
||||
|
||||
## License
|
||||
|
||||
|
||||
@@ -1,246 +1,263 @@
|
||||
{
|
||||
"extensions": {
|
||||
"recommendations": [
|
||||
"charliermarsh.ruff",
|
||||
"esbenp.prettier-vscode",
|
||||
"ms-edgedevtools.vscode-edge-devtools",
|
||||
"ms-python.debugpy",
|
||||
"ms-python.python",
|
||||
"ms-python.vscode-pylance",
|
||||
"samuelcolvin.jinjahtml",
|
||||
"vscode.css-language-features",
|
||||
"vscode.html-language-features",
|
||||
"extensions": {
|
||||
"recommendations": [
|
||||
"charliermarsh.ruff",
|
||||
"esbenp.prettier-vscode",
|
||||
"ms-edgedevtools.vscode-edge-devtools",
|
||||
"ms-python.debugpy",
|
||||
"ms-python.python",
|
||||
"ms-python.vscode-pylance",
|
||||
"samuelcolvin.jinjahtml",
|
||||
"vscode.css-language-features",
|
||||
"vscode.html-language-features"
|
||||
]
|
||||
},
|
||||
"folders": [
|
||||
{
|
||||
"name": "StaticGalleryBuilder",
|
||||
"path": "./"
|
||||
}
|
||||
],
|
||||
"launch": {
|
||||
"version": "0.2.0",
|
||||
"configurations": [
|
||||
{
|
||||
"args": [
|
||||
"-p",
|
||||
"${workspaceFolder}/test",
|
||||
"-w",
|
||||
"file://${workspaceFolder}/test",
|
||||
"-t",
|
||||
"Pictures",
|
||||
"--theme",
|
||||
"themes/alpenglow.css",
|
||||
"--use-fancy-folders",
|
||||
"--web-manifest",
|
||||
"-l",
|
||||
"cc-by-nc-sa",
|
||||
"-n",
|
||||
"-m",
|
||||
"--reverse-sort",
|
||||
"--regenerate-thumbnails",
|
||||
"--reread-metadata",
|
||||
"--folderthumbnails"
|
||||
],
|
||||
"console": "integratedTerminal",
|
||||
"name": "Testfolder",
|
||||
"postDebugTask": "Delete Lockfile",
|
||||
"program": "${workspaceFolder}/builder.py",
|
||||
"request": "launch",
|
||||
"type": "debugpy"
|
||||
},
|
||||
{
|
||||
"args": [
|
||||
"-p",
|
||||
"/home/user/woek/Pictures",
|
||||
"-w",
|
||||
"file:///home/user/woek/Pictures",
|
||||
"-t",
|
||||
"Pictures",
|
||||
"--theme",
|
||||
"themes/default.css",
|
||||
"--use-fancy-folders",
|
||||
"--web-manifest",
|
||||
"-n",
|
||||
"-m",
|
||||
// "--regenerate-thumbnails",
|
||||
// "--reread-metadata",
|
||||
"--folderthumbnails"
|
||||
],
|
||||
"console": "integratedTerminal",
|
||||
"name": "woek",
|
||||
"postDebugTask": "Delete Lockfile 2",
|
||||
"program": "${workspaceFolder}/builder.py",
|
||||
"request": "launch",
|
||||
"type": "debugpy"
|
||||
},
|
||||
{
|
||||
"args": [
|
||||
"--use-fancy-folders",
|
||||
"-p",
|
||||
"/mnt/nfs/pictures/",
|
||||
"-w",
|
||||
"https://pictures.sorogon.eu/",
|
||||
"-t",
|
||||
"Sorogon's Pictures",
|
||||
"--theme",
|
||||
"/home/user/git/github.com/greflm13/simple-picture-server/themes/alpenglow.css",
|
||||
"-m",
|
||||
"--exclude-folder",
|
||||
"Scans",
|
||||
"--exclude-folder",
|
||||
"*/Galleries/*",
|
||||
"--folderthumbnails",
|
||||
"--reread-metadata"
|
||||
],
|
||||
"console": "integratedTerminal",
|
||||
"name": "production",
|
||||
"program": "${workspaceFolder}/builder.py",
|
||||
"request": "launch",
|
||||
"type": "debugpy"
|
||||
},
|
||||
{
|
||||
"args": [
|
||||
"${workspaceFolder}/themes",
|
||||
"https://pictures.sorogon.eu/public/Example/"
|
||||
],
|
||||
"console": "integratedTerminal",
|
||||
"name": "Generate Themes previews",
|
||||
"program": "${workspaceFolder}/generate_previews.py",
|
||||
"request": "launch",
|
||||
"type": "debugpy"
|
||||
}
|
||||
]
|
||||
},
|
||||
"settings": {
|
||||
"[css]": {
|
||||
"editor.defaultFormatter": "vscode.css-language-features"
|
||||
},
|
||||
"folders": [
|
||||
{
|
||||
"name": "StaticGalleryBuilder",
|
||||
"path": "./",
|
||||
},
|
||||
"[jinja-css]": {
|
||||
"editor.defaultFormatter": "vscode.css-language-features"
|
||||
},
|
||||
"[jinja-html]": {
|
||||
"editor.defaultFormatter": "vscode.html-language-features"
|
||||
},
|
||||
"[jinja-js]": {
|
||||
"editor.defaultFormatter": "esbenp.prettier-vscode"
|
||||
},
|
||||
"[python]": {
|
||||
"editor.defaultFormatter": "charliermarsh.ruff"
|
||||
},
|
||||
"black-formatter.args": ["-l 260"],
|
||||
"black-formatter.interpreter": ["/usr/bin/python3"],
|
||||
"editor.formatOnSave": false,
|
||||
"emmet.includeLanguages": {
|
||||
"jinja-css": "css",
|
||||
"jinja-html": "html",
|
||||
"jinja-js": "javascript",
|
||||
"jinja-json": "json"
|
||||
},
|
||||
"files.associations": {
|
||||
"**/*.css.j2": "jinja-css",
|
||||
"**/*.css": "css",
|
||||
"**/*.html.j2": "jinja-html"
|
||||
},
|
||||
"gitblame.inlineMessageEnabled": true,
|
||||
"gitblame.inlineMessageFormat": "${author.name}, ${time.ago} • ${commit.summary}",
|
||||
"gitblame.statusBarMessageFormat": "${author.name} (${time.ago})",
|
||||
"html.format.indentHandlebars": true,
|
||||
"html.format.templating": true,
|
||||
"html.format.wrapAttributes": "preserve",
|
||||
"html.format.wrapLineLength": 200,
|
||||
"html.hover.documentation": true,
|
||||
"html.suggest.html5": true,
|
||||
"html.validate.scripts": true,
|
||||
"html.validate.styles": true,
|
||||
"json.schemaDownload.enable": true,
|
||||
"json.schemas": [
|
||||
{
|
||||
"fileMatch": ["manifest.json.j2"],
|
||||
"url": "https://json.schemastore.org/web-manifest-combined.json"
|
||||
}
|
||||
],
|
||||
"launch": {
|
||||
"version": "0.2.0",
|
||||
"configurations": [
|
||||
{
|
||||
"args": [
|
||||
"-p",
|
||||
"${workspaceFolder}/test",
|
||||
"-w",
|
||||
"file://${workspaceFolder}/test",
|
||||
"-t",
|
||||
"Pictures",
|
||||
"--theme",
|
||||
"themes/alpenglow.css",
|
||||
"--use-fancy-folders",
|
||||
"--web-manifest",
|
||||
"-l",
|
||||
"cc-by-nc-sa",
|
||||
"-n",
|
||||
"-m",
|
||||
"--reverse-sort",
|
||||
"--regenerate-thumbnails",
|
||||
"--reread-metadata",
|
||||
"--folderthumbnails",
|
||||
],
|
||||
"console": "integratedTerminal",
|
||||
"name": "Testfolder",
|
||||
"postDebugTask": "Delete Lockfile",
|
||||
"program": "${workspaceFolder}/builder.py",
|
||||
"request": "launch",
|
||||
"type": "debugpy",
|
||||
},
|
||||
{
|
||||
"args": [
|
||||
"-p",
|
||||
"/home/user/woek/Pictures",
|
||||
"-w",
|
||||
"file:///home/user/woek/Pictures",
|
||||
"-t",
|
||||
"Pictures",
|
||||
"--theme",
|
||||
"themes/default.css",
|
||||
"--use-fancy-folders",
|
||||
"--web-manifest",
|
||||
"-n",
|
||||
"-m",
|
||||
// "--regenerate-thumbnails",
|
||||
// "--reread-metadata",
|
||||
"--folderthumbnails",
|
||||
],
|
||||
"console": "integratedTerminal",
|
||||
"name": "woek",
|
||||
"postDebugTask": "Delete Lockfile 2",
|
||||
"program": "${workspaceFolder}/builder.py",
|
||||
"request": "launch",
|
||||
"type": "debugpy",
|
||||
},
|
||||
{
|
||||
"args": [
|
||||
"${workspaceFolder}/themes",
|
||||
"https://pictures.sorogon.eu/Analog/Example/"
|
||||
],
|
||||
"console": "integratedTerminal",
|
||||
"name": "Generate Themes previews",
|
||||
"program": "${workspaceFolder}/generate_previews.py",
|
||||
"request": "launch",
|
||||
"type": "debugpy",
|
||||
}
|
||||
],
|
||||
"prettier.htmlWhitespaceSensitivity": "css",
|
||||
"pylint.args": [
|
||||
"--disable=C0111",
|
||||
"--disable=C0301",
|
||||
"--good-names-rgxs=^[_a-z][_a-z0-9]?$"
|
||||
],
|
||||
"python.analysis.inlayHints.callArgumentNames": "off",
|
||||
"python.analysis.inlayHints.functionReturnTypes": false,
|
||||
"python.analysis.inlayHints.variableTypes": false,
|
||||
"yaml.schemas": {
|
||||
"https://raw.githubusercontent.com/pamburus/hl/master/schema/json/config.schema.json": "file:///home/user/git/github.com/greflm13/StaticGalleryBuilder/hl_config.yaml"
|
||||
},
|
||||
"settings": {
|
||||
"[css]": {
|
||||
"editor.defaultFormatter": "vscode.css-language-features",
|
||||
"ruff.lineLength": 180
|
||||
},
|
||||
"tasks": {
|
||||
"version": "2.0.0",
|
||||
"tasks": [
|
||||
{
|
||||
"command": "rm -f ${workspaceFolder}/test/.lock",
|
||||
"isBackground": true,
|
||||
"label": "Delete Lockfile",
|
||||
"problemMatcher": [],
|
||||
"type": "shell",
|
||||
"presentation": {
|
||||
"echo": false,
|
||||
"reveal": "never",
|
||||
"focus": false,
|
||||
"panel": "shared",
|
||||
"showReuseMessage": false,
|
||||
"clear": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"command": "rm -f /home/user/woek/Pictures/.lock",
|
||||
"isBackground": true,
|
||||
"label": "Delete Lockfile 2",
|
||||
"problemMatcher": [],
|
||||
"type": "shell",
|
||||
"presentation": {
|
||||
"echo": false,
|
||||
"reveal": "never",
|
||||
"focus": false,
|
||||
"panel": "shared",
|
||||
"showReuseMessage": false,
|
||||
"clear": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"command": "pyinstaller builder.py modules/*.py -n StaticGalleryBuilder-$(cat .version)-linux -F --add-data files:files --add-data templates:templates --add-data .version:.",
|
||||
"isBackground": false,
|
||||
"label": "Build",
|
||||
"problemMatcher": [],
|
||||
"type": "shell",
|
||||
"presentation": {
|
||||
"echo": true,
|
||||
"reveal": "always",
|
||||
"focus": false,
|
||||
"panel": "shared",
|
||||
"showReuseMessage": false,
|
||||
"clear": false
|
||||
},
|
||||
"[jinja-css]": {
|
||||
"editor.defaultFormatter": "vscode.css-language-features",
|
||||
"group": {
|
||||
"kind": "build",
|
||||
"isDefault": true
|
||||
},
|
||||
"[jinja-html]": {
|
||||
"editor.defaultFormatter": "vscode.html-language-features",
|
||||
"dependsOn": ["Clean"]
|
||||
},
|
||||
{
|
||||
"command": "rm -rf build dist",
|
||||
"isBackground": true,
|
||||
"label": "Clean",
|
||||
"problemMatcher": [],
|
||||
"type": "shell",
|
||||
"presentation": {
|
||||
"echo": true,
|
||||
"reveal": "never",
|
||||
"focus": false,
|
||||
"panel": "shared",
|
||||
"showReuseMessage": false,
|
||||
"clear": true
|
||||
},
|
||||
"[jinja-js]": {
|
||||
"editor.defaultFormatter": "esbenp.prettier-vscode",
|
||||
},
|
||||
"[python]": {
|
||||
"editor.defaultFormatter": "charliermarsh.ruff",
|
||||
},
|
||||
"black-formatter.args": [
|
||||
"-l 260",
|
||||
],
|
||||
"black-formatter.interpreter": [
|
||||
"/usr/bin/python3",
|
||||
],
|
||||
"editor.formatOnSave": false,
|
||||
"emmet.includeLanguages": {
|
||||
"jinja-css": "css",
|
||||
"jinja-html": "html",
|
||||
"jinja-js": "javascript",
|
||||
"jinja-json": "json",
|
||||
},
|
||||
"files.associations": {
|
||||
"**/*.css.j2": "jinja-css",
|
||||
"**/*.css": "css",
|
||||
"**/*.html.j2": "jinja-html",
|
||||
},
|
||||
"gitblame.inlineMessageEnabled": true,
|
||||
"gitblame.inlineMessageFormat": "${author.name}, ${time.ago} • ${commit.summary}",
|
||||
"gitblame.statusBarMessageFormat": "${author.name} (${time.ago})",
|
||||
"html.format.indentHandlebars": true,
|
||||
"html.format.templating": true,
|
||||
"html.format.wrapAttributes": "preserve",
|
||||
"html.format.wrapLineLength": 200,
|
||||
"html.hover.documentation": true,
|
||||
"html.suggest.html5": true,
|
||||
"html.validate.scripts": true,
|
||||
"html.validate.styles": true,
|
||||
"json.schemaDownload.enable": true,
|
||||
"json.schemas": [
|
||||
{
|
||||
"fileMatch": [
|
||||
"manifest.json.j2",
|
||||
],
|
||||
"url": "https://json.schemastore.org/web-manifest-combined.json",
|
||||
},
|
||||
],
|
||||
"prettier.htmlWhitespaceSensitivity": "css",
|
||||
"pylint.args": [
|
||||
"--disable=C0111",
|
||||
"--disable=C0301",
|
||||
"--good-names-rgxs=^[_a-z][_a-z0-9]?$",
|
||||
],
|
||||
"python.analysis.inlayHints.callArgumentNames": "off",
|
||||
"python.analysis.inlayHints.functionReturnTypes": false,
|
||||
"python.analysis.inlayHints.variableTypes": false,
|
||||
"yaml.schemas": {
|
||||
"https://raw.githubusercontent.com/pamburus/hl/master/schema/json/config.schema.json": "file:///home/user/git/github.com/greflm13/StaticGalleryBuilder/hl_config.yaml"
|
||||
},
|
||||
"ruff.lineLength": 180,
|
||||
},
|
||||
"tasks": {
|
||||
"version": "2.0.0",
|
||||
"tasks": [
|
||||
{
|
||||
"command": "rm -f ${workspaceFolder}/test/.lock",
|
||||
"isBackground": true,
|
||||
"label": "Delete Lockfile",
|
||||
"problemMatcher": [],
|
||||
"type": "shell",
|
||||
"presentation": {
|
||||
"echo": false,
|
||||
"reveal": "never",
|
||||
"focus": false,
|
||||
"panel": "shared",
|
||||
"showReuseMessage": false,
|
||||
"clear": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"command": "rm -f /home/user/woek/Pictures/.lock",
|
||||
"isBackground": true,
|
||||
"label": "Delete Lockfile 2",
|
||||
"problemMatcher": [],
|
||||
"type": "shell",
|
||||
"presentation": {
|
||||
"echo": false,
|
||||
"reveal": "never",
|
||||
"focus": false,
|
||||
"panel": "shared",
|
||||
"showReuseMessage": false,
|
||||
"clear": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"command": "pyinstaller builder.py modules/*.py -n StaticGalleryBuilder-$(cat .version)-linux -F --add-data files:files --add-data templates:templates --add-data .version:.",
|
||||
"isBackground": false,
|
||||
"label": "Build",
|
||||
"problemMatcher": [],
|
||||
"type": "shell",
|
||||
"presentation": {
|
||||
"echo": true,
|
||||
"reveal": "always",
|
||||
"focus": false,
|
||||
"panel": "shared",
|
||||
"showReuseMessage": false,
|
||||
"clear": false
|
||||
},
|
||||
"group": {
|
||||
"kind": "build",
|
||||
"isDefault": true
|
||||
},
|
||||
"dependsOn": [
|
||||
"Clean"
|
||||
]
|
||||
},
|
||||
{
|
||||
"command": "rm -rf build dist",
|
||||
"isBackground": true,
|
||||
"label": "Clean",
|
||||
"problemMatcher": [],
|
||||
"type": "shell",
|
||||
"presentation": {
|
||||
"echo": true,
|
||||
"reveal": "never",
|
||||
"focus": false,
|
||||
"panel": "shared",
|
||||
"showReuseMessage": false,
|
||||
"clear": true
|
||||
},
|
||||
"group": "build"
|
||||
},
|
||||
{
|
||||
"command": "LESS=-SR hl logs/latest.jsonl --config hl_config.yaml",
|
||||
"isBackground": false,
|
||||
"label": "View Latest Log",
|
||||
"problemMatcher": [],
|
||||
"type": "shell",
|
||||
"presentation": {
|
||||
"echo": false,
|
||||
"reveal": "always",
|
||||
"focus": true,
|
||||
"panel": "dedicated",
|
||||
"showReuseMessage": false,
|
||||
"clear": true
|
||||
}
|
||||
}
|
||||
],
|
||||
},
|
||||
}
|
||||
"group": "build"
|
||||
},
|
||||
{
|
||||
"command": "LESS=-SR hl logs/latest.jsonl --config hl_config.yaml",
|
||||
"isBackground": false,
|
||||
"label": "View Latest Log",
|
||||
"problemMatcher": [],
|
||||
"type": "shell",
|
||||
"presentation": {
|
||||
"echo": false,
|
||||
"reveal": "always",
|
||||
"focus": true,
|
||||
"panel": "dedicated",
|
||||
"showReuseMessage": false,
|
||||
"clear": true
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -34,8 +34,6 @@ IMG_EXTENSIONS = [".jpg", ".jpeg", ".png"]
|
||||
NOT_LIST = ["*/Galleries/*", "Archives"]
|
||||
# fmt: on
|
||||
|
||||
pbardict: dict[str, tqdm] = {}
|
||||
|
||||
args = parse_arguments(VERSION)
|
||||
|
||||
lock_file = os.path.join(args.root_directory, ".lock")
|
||||
@@ -45,7 +43,7 @@ if os.path.exists(lock_file):
|
||||
else:
|
||||
from modules.logger import logger
|
||||
from modules.svg_handling import icons, webmanifest, extract_colorscheme
|
||||
from modules.generate_html import list_folder, EXCLUDES
|
||||
from modules.generate_html import list_folder
|
||||
|
||||
|
||||
def init_globals(_args: Args, raw: list[str]) -> tuple[Args, list[str]]:
|
||||
|
||||
@@ -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,31 @@ 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;
|
||||
max-height: 286px;
|
||||
overflow: scroll;
|
||||
}
|
||||
|
||||
.tooltip .infotext {
|
||||
padding: 12px;
|
||||
}
|
||||
|
||||
.tooltip .tagdropdown {
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.tooltip:hover .tooltiptext {
|
||||
display: block;
|
||||
opacity: 1;
|
||||
@@ -172,6 +189,27 @@ figure {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.tooltip .tooltiptext .tagentry {
|
||||
list-style: none;
|
||||
width: 100%;
|
||||
cursor: pointer;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.tooltip .tooltiptext ol {
|
||||
margin-left: 0;
|
||||
padding-left: 0.5em;
|
||||
}
|
||||
|
||||
.tooltip .tooltiptext .tagentry label {
|
||||
cursor: pointer;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
padding: 12px;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.column {
|
||||
-ms-flex: 12.5%;
|
||||
flex: 12.5%;
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import os
|
||||
import re
|
||||
import sys
|
||||
import time
|
||||
import shutil
|
||||
import base64
|
||||
import fileinput
|
||||
|
||||
@@ -5,10 +5,12 @@ import fnmatch
|
||||
import json
|
||||
from typing import Any
|
||||
from datetime import datetime
|
||||
from collections import defaultdict
|
||||
|
||||
from tqdm.auto import tqdm
|
||||
from PIL import Image, ExifTags, TiffImagePlugin
|
||||
from PIL import Image, ExifTags, TiffImagePlugin, UnidentifiedImageError
|
||||
from jinja2 import Environment, FileSystemLoader
|
||||
from defusedxml import ElementTree
|
||||
|
||||
from modules.logger import logger
|
||||
from modules import cclicense
|
||||
@@ -29,55 +31,95 @@ 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] = {}
|
||||
pbardict: dict[str, tqdm] = {}
|
||||
|
||||
|
||||
def initialize_sizelist(folder: str) -> dict[str, dict[str, int]]:
|
||||
def getxmp(strbuffer: str) -> dict[str, Any]:
|
||||
"""
|
||||
Initializes the size list JSON file if it doesn't exist.
|
||||
Returns a dictionary containing the XMP tags.
|
||||
Requires defusedxml to be installed.
|
||||
|
||||
:returns: XMP tags in a dictionary.
|
||||
"""
|
||||
|
||||
def get_name(tag: str) -> str:
|
||||
return re.sub("^{[^}]+}", "", tag)
|
||||
|
||||
def get_value(element) -> str | dict[str, Any] | None:
|
||||
value: dict[str, Any] = {get_name(k): v for k, v in element.attrib.items()}
|
||||
children = list(element)
|
||||
if children:
|
||||
for child in children:
|
||||
name = get_name(child.tag)
|
||||
child_value = get_value(child)
|
||||
if name in value:
|
||||
if not isinstance(value[name], list):
|
||||
value[name] = [value[name]]
|
||||
value[name].append(child_value)
|
||||
else:
|
||||
value[name] = child_value
|
||||
elif value:
|
||||
if element.text:
|
||||
value["text"] = element.text
|
||||
else:
|
||||
return element.text
|
||||
return value
|
||||
|
||||
root = ElementTree.fromstring(strbuffer)
|
||||
return {get_name(root.tag): get_value(root)}
|
||||
|
||||
|
||||
def initialize_metadata(folder: str) -> dict[str, dict[str, int]]:
|
||||
"""
|
||||
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]:
|
||||
@@ -92,10 +134,17 @@ 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})
|
||||
width, height = img.size
|
||||
exif = img.getexif()
|
||||
xmpdata = img.getxmp()
|
||||
|
||||
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, "xmp": None}
|
||||
if exif:
|
||||
logger.info("extracting EXIF data", extra={"file": file})
|
||||
ifd = exif.get_ifd(ExifTags.IFD.Exif)
|
||||
@@ -117,9 +166,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:
|
||||
@@ -131,12 +180,129 @@ 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}
|
||||
else:
|
||||
return {"width": width, "height": height, "exifdata": None}
|
||||
exifdata = None
|
||||
tags = []
|
||||
xmp = None
|
||||
if xmpdata:
|
||||
logger.info("extracting XMP data", extra={"file": file})
|
||||
try:
|
||||
tags = xmpdata["xmpmeta"]["RDF"]["Description"]["subject"]["Bag"]["li"]
|
||||
if isinstance(tags, str):
|
||||
tags = [tags]
|
||||
except TypeError:
|
||||
pass
|
||||
except KeyError:
|
||||
pass
|
||||
try:
|
||||
tags = xmpdata["xapmeta"]["RDF"]["Description"]["subject"]["Bag"]["li"]
|
||||
if isinstance(tags, str):
|
||||
tags = [tags]
|
||||
except TypeError:
|
||||
pass
|
||||
except KeyError:
|
||||
pass
|
||||
try:
|
||||
tags = xmpdata["xmpmeta"]["RDF"]["Description"]["hierarchicalSubject"]["Bag"]["li"]
|
||||
if isinstance(tags, str):
|
||||
tags = [tags]
|
||||
except TypeError:
|
||||
pass
|
||||
except KeyError:
|
||||
pass
|
||||
try:
|
||||
tags = xmpdata["xapmeta"]["RDF"]["Description"]["hierarchicalSubject"]["Bag"]["li"]
|
||||
if isinstance(tags, str):
|
||||
tags = [tags]
|
||||
except TypeError:
|
||||
pass
|
||||
except KeyError:
|
||||
pass
|
||||
if None in tags:
|
||||
tags.remove(None)
|
||||
return {"width": width, "height": height, "tags": tags, "exifdata": exifdata, "xmp": xmp}
|
||||
|
||||
|
||||
def process_image(item: str, folder: str, _args: Args, baseurl: str, sizelist: dict[str, dict[str, int]], raw: list[str]) -> dict[str, Any]:
|
||||
def nested_dict():
|
||||
return defaultdict(nested_dict)
|
||||
|
||||
|
||||
def insert_path(d, path):
|
||||
for part in path[:-1]:
|
||||
d = d[part]
|
||||
last = path[-1]
|
||||
if not isinstance(d[last], dict):
|
||||
d[last] = {}
|
||||
|
||||
|
||||
def finalize(d):
|
||||
if isinstance(d, defaultdict):
|
||||
# Sort keys before recursion
|
||||
return {k: finalize(d[k]) for k in sorted(d)}
|
||||
return d or []
|
||||
|
||||
|
||||
def parse_hierarchical_tags(tags, delimiter="|"):
|
||||
tree = nested_dict()
|
||||
for tag in tags:
|
||||
parts = tag.split(delimiter)
|
||||
insert_path(tree, parts)
|
||||
return finalize(tree)
|
||||
|
||||
|
||||
def get_tags(sidecarfile: str) -> list[str]:
|
||||
"""
|
||||
Extracts Tags from XMP sidecar file
|
||||
|
||||
Args:
|
||||
sidecarfile (str): The path to the XMP sidecar file.
|
||||
|
||||
Returns:
|
||||
list[str]: List containing image tags.
|
||||
"""
|
||||
logger.info("extracting XMP sidecar file data", extra={"file": sidecarfile})
|
||||
with open(sidecarfile) as sidecar:
|
||||
strbuffer = sidecar.read()
|
||||
xmpdata = getxmp(strbuffer)
|
||||
tags = []
|
||||
try:
|
||||
tags = xmpdata["xmpmeta"]["RDF"]["Description"]["subject"]["Bag"]["li"]
|
||||
if isinstance(tags, str):
|
||||
tags = [tags]
|
||||
except TypeError:
|
||||
pass
|
||||
except KeyError:
|
||||
pass
|
||||
try:
|
||||
tags = xmpdata["xapmeta"]["RDF"]["Description"]["subject"]["Bag"]["li"]
|
||||
if isinstance(tags, str):
|
||||
tags = [tags]
|
||||
except TypeError:
|
||||
pass
|
||||
except KeyError:
|
||||
pass
|
||||
try:
|
||||
tags = xmpdata["xmpmeta"]["RDF"]["Description"]["hierarchicalSubject"]["Bag"]["li"]
|
||||
if isinstance(tags, str):
|
||||
tags = [tags]
|
||||
except TypeError:
|
||||
pass
|
||||
except KeyError:
|
||||
pass
|
||||
try:
|
||||
tags = xmpdata["xapmeta"]["RDF"]["Description"]["hierarchicalSubject"]["Bag"]["li"]
|
||||
if isinstance(tags, str):
|
||||
tags = [tags]
|
||||
except TypeError:
|
||||
pass
|
||||
except KeyError:
|
||||
pass
|
||||
if None in tags:
|
||||
tags.remove(None)
|
||||
return tags
|
||||
|
||||
|
||||
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.
|
||||
|
||||
@@ -145,23 +311,32 @@ 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)
|
||||
sidecarfile = os.path.join(folder, item + ".xmp")
|
||||
if os.path.exists(sidecarfile):
|
||||
logger.info("xmp sidecar file found", extra={"file": sidecarfile})
|
||||
try:
|
||||
metadata[item]["tags"] = get_tags(sidecarfile)
|
||||
except Exception as e:
|
||||
logger.error(e)
|
||||
|
||||
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", ""),
|
||||
"xmp": metadata[item].get("xmp", ""),
|
||||
}
|
||||
path = os.path.join(_args.root_directory, ".thumbnails", baseurl, item + ".jpg")
|
||||
if not os.path.exists(path) or _args.regenerate_thumbnails:
|
||||
@@ -194,10 +369,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
|
||||
@@ -218,7 +393,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":
|
||||
@@ -231,13 +406,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)
|
||||
@@ -261,7 +436,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.
|
||||
|
||||
@@ -366,6 +541,12 @@ def create_html_file(folder: str, title: str, foldername: str, images: list[dict
|
||||
else None
|
||||
)
|
||||
|
||||
alltags = set()
|
||||
for img in images:
|
||||
alltags.update(img["tags"])
|
||||
|
||||
nested_tags = parse_hierarchical_tags(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:
|
||||
@@ -414,6 +595,7 @@ def create_html_file(folder: str, title: str, foldername: str, images: list[dict
|
||||
version=version,
|
||||
logo=logo,
|
||||
licensefile=license_url,
|
||||
tags=nested_tags,
|
||||
)
|
||||
|
||||
with open(html_file, "w", encoding="utf-8") as f:
|
||||
@@ -421,7 +603,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.
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
CairoSVG==2.7.1
|
||||
defusedxml==0.7.1
|
||||
Jinja2==3.1.5
|
||||
Pillow==11.1.0
|
||||
pyinstaller==6.11.1
|
||||
|
||||
@@ -52,6 +52,10 @@
|
||||
background-color: var(--color2);
|
||||
}
|
||||
|
||||
.tagentry > label:hover {
|
||||
background-color: var(--color4);
|
||||
}
|
||||
|
||||
.column img {
|
||||
background-color: var(--color2);
|
||||
}
|
||||
|
||||
@@ -1,3 +1,17 @@
|
||||
{%- macro render_tags(tag_tree, parent) -%}
|
||||
<ol>
|
||||
{%- for key, value in tag_tree.items() %}
|
||||
<li class="tagentry">
|
||||
<label onclick="filter()" title="{{ key }}" id="{{ parent }}|{{ key }}">
|
||||
<input type="checkbox" />{{ key }}
|
||||
</label>
|
||||
{%- if value %}
|
||||
{{ render_tags(value, parent + '|' + key) }}
|
||||
{%- endif %}
|
||||
</li>
|
||||
{%- endfor %}
|
||||
</ol>
|
||||
{%- endmacro -%}
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
|
||||
@@ -31,23 +45,37 @@
|
||||
|
||||
<body>
|
||||
<div class="header">
|
||||
<ul class="navbar">
|
||||
<li><a href="{{ root }}">Home</a></li>
|
||||
{%- if parent %}
|
||||
<li><a href="{{ parent }}">Parent Directory</a></li>
|
||||
{%- endif %}
|
||||
{%- if info %}
|
||||
<li class="tooltip"><a>Info</a><span class="tooltiptext">
|
||||
{%- for infoline in info -%}
|
||||
{{ infoline }}<br />
|
||||
{%- endfor -%}
|
||||
</span></li>
|
||||
{%- endif %}
|
||||
<li class="title"><span class="header">{{ header }}</span></li>
|
||||
{%- if licensefile %}
|
||||
<li class="license"><a href="{{ licensefile }}">License</a></li>
|
||||
{%- endif %}
|
||||
</ul>
|
||||
<ol class="navbar">
|
||||
<div class="navleft">
|
||||
<li><a href="{{ root }}">Home</a></li>
|
||||
{%- if parent %}
|
||||
<li><a href="{{ parent }}">Parent Directory</a></li>
|
||||
{%- endif %}
|
||||
{%- if info %}
|
||||
<li class="tooltip"><a>Info</a><span class="tooltiptext infotext">
|
||||
{%- for infoline in info -%}
|
||||
{{ infoline }}<br />
|
||||
{%- endfor -%}
|
||||
</span></li>
|
||||
{%- endif %}
|
||||
</div>
|
||||
<div class="navcenter">
|
||||
<li class="title"><span class="header">{{ header }}</span></li>
|
||||
</div>
|
||||
<div class="navright">
|
||||
{% if tags %}
|
||||
<li class="tooltip">
|
||||
<a>Filter by Tags</a>
|
||||
<ol class="tooltiptext tagdropdown" id="tagdropdown">
|
||||
{{ render_tags(tags, '') }}
|
||||
</ol>
|
||||
</li>
|
||||
{% endif %}
|
||||
{%- if licensefile %}
|
||||
<li class="license"><a href="{{ licensefile }}">License</a></li>
|
||||
{%- endif %}
|
||||
</div>
|
||||
</ol>
|
||||
{% if subdirectories %}
|
||||
{%- for subdirectory in subdirectories %}
|
||||
<link rel="preload" href="{{ subdirectory.url }}/index.html" type="text/html">
|
||||
@@ -69,23 +97,7 @@
|
||||
</div>
|
||||
{% if images %}
|
||||
{%- set ns = namespace(count = 0) -%}
|
||||
<div class="row">
|
||||
{%- for image in images %}
|
||||
<div class="column">
|
||||
<figure>
|
||||
<img src="{{ image.thumbnail }}" alt="{{ image.name }}" onclick="openSwipe({{ ns.count }})" onmouseover="prefetch({{ ns.count }})" onmouseleave="cancel({{ ns.count }})" />
|
||||
{%- set ns.count = ns.count + 1 %}
|
||||
<figcaption class="caption">{{ image.name }}
|
||||
{%- if image.tiff %}
|
||||
<a href="{{ image.tiff }}">TIFF</a>
|
||||
{%- endif %}
|
||||
{%- if image.raw %}
|
||||
<a href="{{ image.raw }}">RAW</a>
|
||||
{%- endif %}
|
||||
</figcaption>
|
||||
</figure>
|
||||
</div>
|
||||
{%- endfor %}
|
||||
<div class="row" id="imagelist">
|
||||
</div>
|
||||
{%- endif %}
|
||||
{% if license %}
|
||||
@@ -108,14 +120,14 @@
|
||||
{%- endif %}
|
||||
<span class="attribution">Made with <a href="https://github.com/greflm13/StaticGalleryBuilder" target="_blank" rel="noopener noreferrer">StaticGalleryBuilder {{ version }}</a> by <a
|
||||
href="https://github.com/greflm13" target="_blank" rel="noopener noreferrer">{{ logo }}</a>.</span>
|
||||
<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>
|
||||
{%- endif %}
|
||||
{%- else %}
|
||||
<div class="footer">
|
||||
<span class="attribution">Made with <a href="https://github.com/greflm13/StaticGalleryBuilder" target="_blank" rel="noopener noreferrer">StaticGalleryBuilder {{ version }}</a> by <a
|
||||
href="https://github.com/greflm13" target="_blank" rel="noopener noreferrer">{{ logo }}</a>.</span>
|
||||
<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>
|
||||
{%- endif %}
|
||||
{% if images %}
|
||||
@@ -160,28 +172,24 @@
|
||||
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 }}" },
|
||||
{ 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 }}" },
|
||||
{%- else %}
|
||||
{ src: "{{ image.url }}", w: {{ image.width }}, h: {{ image.height }}, msrc: "{{ image.thumbnail }}" },
|
||||
{ name: "{{ image.name }}", tiff: "{{ image.tiff }}", raw: "{{ image.raw }}", src: "{{ image.url }}", w: {{ image.width }}, h: {{ image.height }}, msrc: "{{ image.thumbnail }}", tags: "{{ image.tags }}" },
|
||||
{%- endif %}
|
||||
{%- endfor %}
|
||||
];
|
||||
var re = /pid=(\d+)/;
|
||||
var filterre = /#(.*)/;
|
||||
var controllers = {}
|
||||
|
||||
function openSwipe(img) {
|
||||
var options = {
|
||||
index: img
|
||||
};
|
||||
var gallery = new PhotoSwipe(pswpElement, PhotoSwipeUI_Default, items, options);
|
||||
var gallery = new PhotoSwipe(pswpElement, PhotoSwipeUI_Default, shown, options);
|
||||
gallery.init();
|
||||
}
|
||||
|
||||
if (re.test(window.location.href)) {
|
||||
var pid = window.location.href.match(re)[1];
|
||||
openSwipe(parseInt(pid));
|
||||
}
|
||||
|
||||
let totopbutton = document.getElementById("totop");
|
||||
|
||||
window.onscroll = function () { scrollFunction() };
|
||||
@@ -198,6 +206,23 @@
|
||||
window.scrollTo({ top: 0, behavior: 'smooth' })
|
||||
}
|
||||
|
||||
function updateImageList(images) {
|
||||
var str = ""
|
||||
var imagelist = document.getElementById("imagelist");
|
||||
images.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;
|
||||
if (item.tiff != "") {
|
||||
str += ' <a href="' + item.tiff + '">TIFF</a>';
|
||||
}
|
||||
if (item.raw != "") {
|
||||
str += ' <a href="' + item.raw + '">RAW</a>';
|
||||
}
|
||||
str += '</figcaption></figure></div>';
|
||||
});
|
||||
|
||||
imagelist.innerHTML = str;
|
||||
}
|
||||
|
||||
function prefetch(img) {
|
||||
const controller = new AbortController()
|
||||
const signal = controller.signal
|
||||
@@ -207,13 +232,74 @@
|
||||
fetch(urlToFetch, {
|
||||
method: 'get',
|
||||
signal: signal,
|
||||
}).catch(function (err) {});
|
||||
}).catch(function (err) { });
|
||||
}
|
||||
|
||||
function cancel(img) {
|
||||
controllers[img].abort();
|
||||
delete controllers[img];
|
||||
}
|
||||
|
||||
function filter() {
|
||||
window.location.href = window.location.href.split("#")[0] + "#";
|
||||
|
||||
const selected_tags = [];
|
||||
const shown = [];
|
||||
|
||||
const tagcheckboxes = document.querySelectorAll("#tagdropdown input[type='checkbox']:checked");
|
||||
|
||||
tagcheckboxes.forEach((checkbox) => {
|
||||
const tag = checkbox.parentElement.id.trim().substring(1);
|
||||
selected_tags.push(tag);
|
||||
});
|
||||
console.log(selected_tags);
|
||||
|
||||
const urltags = selected_tags.join(",");
|
||||
|
||||
items.forEach((item) => {
|
||||
const tags = item.tags || [];
|
||||
const include = selected_tags.every(tag => tags.includes(tag));
|
||||
if (include || selected_tags.length === 0) {
|
||||
shown.push(item);
|
||||
}
|
||||
});
|
||||
|
||||
updateImageList(shown);
|
||||
window.location.href += urltags;
|
||||
}
|
||||
|
||||
function setFilter(selected) {
|
||||
tagdropdown = document.getElementById("tagdropdown").getElementsByTagName("li");
|
||||
selected.forEach((tag) => {
|
||||
for (var i = 0; i < tagdropdown.length; i++) {
|
||||
if (tagdropdown[i].innerText == tag) {
|
||||
tagdropdown[i].firstChild.firstChild.checked = true;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function onLoad() {
|
||||
{%- if tags | length > 0 %}
|
||||
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("load", onLoad, false) :
|
||||
window.attachEvent && window.attachEvent("onload", onLoad);
|
||||
|
||||
</script>
|
||||
{%- endif %}
|
||||
</body>
|
||||
|
||||
@@ -54,14 +54,14 @@
|
||||
{%- endif %}
|
||||
<span class="attribution">Made with <a href="https://github.com/greflm13/StaticGalleryBuilder" target="_blank" rel="noopener noreferrer">StaticGalleryBuilder {{ version }}</a> by <a
|
||||
href="https://github.com/greflm13" target="_blank" rel="noopener noreferrer">{{ logo }}</a>.</span>
|
||||
<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>
|
||||
{%- endif %}
|
||||
{%- else %}
|
||||
<div class="footer">
|
||||
<span class="attribution">Made with <a href="https://github.com/greflm13/StaticGalleryBuilder" target="_blank" rel="noopener noreferrer">StaticGalleryBuilder {{ version }}</a> by <a
|
||||
href="https://github.com/greflm13" target="_blank" rel="noopener noreferrer">{{ logo }}</a>.</span>
|
||||
<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>
|
||||
{%- endif %}
|
||||
</body>
|
||||
BIN
test/example/000041900001.jpg
Normal file
|
After Width: | Height: | Size: 7.3 MiB |
27
test/example/000041900001.jpg.xmp
Normal file
@@ -0,0 +1,27 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<x:xmpmeta x:xmptk="XMP Core 4.4.0-Exiv2" xmlns:x="adobe:ns:meta/">
|
||||
<rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
|
||||
<rdf:Description rdf:about="" xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:exif="http://ns.adobe.com/exif/1.0/" xmlns:lr="http://ns.adobe.com/lightroom/1.0/"
|
||||
xmlns:xmp="http://ns.adobe.com/xap/1.0/" xmlns:xmpMM="http://ns.adobe.com/xap/1.0/mm/"
|
||||
xmpMM:DerivedFrom="000041900001.jpg">
|
||||
<dc:subject>
|
||||
<rdf:Bag>
|
||||
<rdf:li>st</rdf:li>
|
||||
<rdf:li>cloud</rdf:li>
|
||||
<rdf:li>cloudy</rdf:li>
|
||||
<rdf:li>fly</rdf:li>
|
||||
<rdf:li>sky</rdf:li>
|
||||
</rdf:Bag>
|
||||
</dc:subject>
|
||||
<lr:hierarchicalSubject>
|
||||
<rdf:Bag>
|
||||
<rdf:li>st|cloud</rdf:li>
|
||||
<rdf:li>st|cloudy</rdf:li>
|
||||
<rdf:li>st|fly</rdf:li>
|
||||
<rdf:li>st|sky</rdf:li>
|
||||
</rdf:Bag>
|
||||
</lr:hierarchicalSubject>
|
||||
</rdf:Description>
|
||||
</rdf:RDF>
|
||||
</x:xmpmeta>
|
||||
BIN
test/example/000041900001.tif
Normal file
7
test/example/000041900001.tif.xmp
Normal file
@@ -0,0 +1,7 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<x:xmpmeta x:xmptk="XMP Core 4.4.0-Exiv2" xmlns:x="adobe:ns:meta/">
|
||||
<rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
|
||||
<rdf:Description rdf:about="" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:exif="http://ns.adobe.com/exif/1.0/" xmlns:lr="http://ns.adobe.com/lightroom/1.0/" xmlns:xmp="http://ns.adobe.com/xap/1.0/" xmlns:xmpMM="http://ns.adobe.com/xap/1.0/mm/" xmpMM:DerivedFrom="000041900001.tif">
|
||||
<dc:subject><rdf:Bag><rdf:li>st</rdf:li><rdf:li>cloud</rdf:li><rdf:li>cloudy</rdf:li><rdf:li>fly</rdf:li><rdf:li>sky</rdf:li></rdf:Bag></dc:subject><lr:hierarchicalSubject><rdf:Bag><rdf:li>st|cloud</rdf:li><rdf:li>st|cloudy</rdf:li><rdf:li>st|fly</rdf:li><rdf:li>st|sky</rdf:li></rdf:Bag></lr:hierarchicalSubject></rdf:Description>
|
||||
</rdf:RDF>
|
||||
</x:xmpmeta>
|
||||
BIN
test/example/DSC00009.jpg
Normal file
|
After Width: | Height: | Size: 28 MiB |
7
test/example/DSC00009.jpg.xmp
Normal file
@@ -0,0 +1,7 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<x:xmpmeta x:xmptk="XMP Core 4.4.0-Exiv2" xmlns:x="adobe:ns:meta/">
|
||||
<rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
|
||||
<rdf:Description rdf:about="" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:exif="http://ns.adobe.com/exif/1.0/" xmlns:lr="http://ns.adobe.com/lightroom/1.0/" xmlns:xmp="http://ns.adobe.com/xap/1.0/" xmlns:xmpMM="http://ns.adobe.com/xap/1.0/mm/" xmpMM:DerivedFrom="DSC00009.jpg">
|
||||
<dc:subject><rdf:Bag><rdf:li>st</rdf:li><rdf:li>aqueduct</rdf:li><rdf:li>arch</rdf:li><rdf:li>arch bridge</rdf:li><rdf:li>bridge</rdf:li><rdf:li>hillside</rdf:li><rdf:li>passenger train</rdf:li><rdf:li>railroad</rdf:li><rdf:li>railroad bridge</rdf:li><rdf:li>span</rdf:li><rdf:li>train track</rdf:li><rdf:li>tree</rdf:li><rdf:li>viaduct</rdf:li></rdf:Bag></dc:subject><lr:hierarchicalSubject><rdf:Bag><rdf:li>st|aqueduct</rdf:li><rdf:li>st|arch</rdf:li><rdf:li>st|arch bridge</rdf:li><rdf:li>st|bridge</rdf:li><rdf:li>st|hillside</rdf:li><rdf:li>st|passenger train</rdf:li><rdf:li>st|railroad</rdf:li><rdf:li>st|railroad bridge</rdf:li><rdf:li>st|span</rdf:li><rdf:li>st|train track</rdf:li><rdf:li>st|tree</rdf:li><rdf:li>st|viaduct</rdf:li></rdf:Bag></lr:hierarchicalSubject></rdf:Description>
|
||||
</rdf:RDF>
|
||||
</x:xmpmeta>
|
||||
BIN
test/example/DSC01106.jpg
Normal file
|
After Width: | Height: | Size: 3.5 MiB |
7
test/example/DSC01106.jpg.xmp
Normal file
@@ -0,0 +1,7 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<x:xmpmeta x:xmptk="XMP Core 4.4.0-Exiv2" xmlns:x="adobe:ns:meta/">
|
||||
<rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
|
||||
<rdf:Description rdf:about="" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:exif="http://ns.adobe.com/exif/1.0/" xmlns:lr="http://ns.adobe.com/lightroom/1.0/" xmlns:xmp="http://ns.adobe.com/xap/1.0/" xmlns:xmpMM="http://ns.adobe.com/xap/1.0/mm/" xmpMM:DerivedFrom="DSC01106.jpg">
|
||||
<dc:subject><rdf:Bag><rdf:li>st</rdf:li><rdf:li>clear</rdf:li><rdf:li>dark</rdf:li><rdf:li>moon</rdf:li><rdf:li>night</rdf:li><rdf:li>night sky</rdf:li><rdf:li>sky</rdf:li></rdf:Bag></dc:subject><lr:hierarchicalSubject><rdf:Bag><rdf:li>st|clear</rdf:li><rdf:li>st|dark</rdf:li><rdf:li>st|moon</rdf:li><rdf:li>st|night</rdf:li><rdf:li>st|night sky</rdf:li><rdf:li>st|sky</rdf:li></rdf:Bag></lr:hierarchicalSubject></rdf:Description>
|
||||
</rdf:RDF>
|
||||
</x:xmpmeta>
|
||||
7
test/example/DSC03470.JPG.xmp
Normal file
@@ -0,0 +1,7 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<x:xmpmeta x:xmptk="XMP Core 4.4.0-Exiv2" xmlns:x="adobe:ns:meta/">
|
||||
<rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
|
||||
<rdf:Description rdf:about="" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:exif="http://ns.adobe.com/exif/1.0/" xmlns:lr="http://ns.adobe.com/lightroom/1.0/" xmlns:xmp="http://ns.adobe.com/xap/1.0/" xmlns:xmpMM="http://ns.adobe.com/xap/1.0/mm/" xmpMM:DerivedFrom="DSC03470.JPG">
|
||||
<dc:subject><rdf:Bag><rdf:li>st</rdf:li><rdf:li>bus</rdf:li><rdf:li>illuminate</rdf:li><rdf:li>neon</rdf:li><rdf:li>neon light</rdf:li><rdf:li>night</rdf:li><rdf:li>sign</rdf:li><rdf:li>train car</rdf:li><rdf:li>trolley</rdf:li><rdf:li>window</rdf:li></rdf:Bag></dc:subject><lr:hierarchicalSubject><rdf:Bag><rdf:li>st|bus</rdf:li><rdf:li>st|illuminate</rdf:li><rdf:li>st|neon</rdf:li><rdf:li>st|neon light</rdf:li><rdf:li>st|night</rdf:li><rdf:li>st|sign</rdf:li><rdf:li>st|train car</rdf:li><rdf:li>st|trolley</rdf:li><rdf:li>st|window</rdf:li></rdf:Bag></lr:hierarchicalSubject></rdf:Description>
|
||||
</rdf:RDF>
|
||||
</x:xmpmeta>
|
||||
7
test/example/DSC03508.ARW.xmp
Normal file
@@ -0,0 +1,7 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<x:xmpmeta x:xmptk="XMP Core 4.4.0-Exiv2" xmlns:x="adobe:ns:meta/">
|
||||
<rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
|
||||
<rdf:Description rdf:about="" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:exif="http://ns.adobe.com/exif/1.0/" xmlns:lr="http://ns.adobe.com/lightroom/1.0/" xmlns:xmp="http://ns.adobe.com/xap/1.0/" xmlns:xmpMM="http://ns.adobe.com/xap/1.0/mm/" xmpMM:DerivedFrom="DSC03508.ARW">
|
||||
<dc:subject><rdf:Bag><rdf:li>st</rdf:li><rdf:li>building</rdf:li><rdf:li>ceiling</rdf:li><rdf:li>pillar</rdf:li><rdf:li>display</rdf:li><rdf:li>rail</rdf:li><rdf:li>steam engine</rdf:li><rdf:li>steam locomotive</rdf:li><rdf:li>train</rdf:li><rdf:li>train car</rdf:li><rdf:li>train track</rdf:li></rdf:Bag></dc:subject><lr:hierarchicalSubject><rdf:Bag><rdf:li>st|building</rdf:li><rdf:li>st|ceiling</rdf:li><rdf:li>st|pillar</rdf:li><rdf:li>st|display</rdf:li><rdf:li>st|rail</rdf:li><rdf:li>st|steam engine</rdf:li><rdf:li>st|steam locomotive</rdf:li><rdf:li>st|train</rdf:li><rdf:li>st|train car</rdf:li><rdf:li>st|train track</rdf:li></rdf:Bag></lr:hierarchicalSubject></rdf:Description>
|
||||
</rdf:RDF>
|
||||
</x:xmpmeta>
|
||||
7
test/example/DSC03508.JPG.xmp
Normal file
@@ -0,0 +1,7 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<x:xmpmeta x:xmptk="XMP Core 4.4.0-Exiv2" xmlns:x="adobe:ns:meta/">
|
||||
<rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
|
||||
<rdf:Description rdf:about="" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:exif="http://ns.adobe.com/exif/1.0/" xmlns:lr="http://ns.adobe.com/lightroom/1.0/" xmlns:xmp="http://ns.adobe.com/xap/1.0/" xmlns:xmpMM="http://ns.adobe.com/xap/1.0/mm/" xmpMM:DerivedFrom="DSC03508.JPG">
|
||||
<dc:subject><rdf:Bag><rdf:li>st</rdf:li><rdf:li>attach</rdf:li><rdf:li>basement</rdf:li><rdf:li>beam</rdf:li><rdf:li>building</rdf:li><rdf:li>ceiling</rdf:li><rdf:li>equipment</rdf:li><rdf:li>floor</rdf:li><rdf:li>pipe</rdf:li><rdf:li>red</rdf:li><rdf:li>room</rdf:li><rdf:li>scaffold</rdf:li><rdf:li>tube</rdf:li><rdf:li>warehouse</rdf:li><rdf:li>water pipe</rdf:li></rdf:Bag></dc:subject><lr:hierarchicalSubject><rdf:Bag><rdf:li>st|attach</rdf:li><rdf:li>st|basement</rdf:li><rdf:li>st|beam</rdf:li><rdf:li>st|building</rdf:li><rdf:li>st|ceiling</rdf:li><rdf:li>st|equipment</rdf:li><rdf:li>st|floor</rdf:li><rdf:li>st|pipe</rdf:li><rdf:li>st|red</rdf:li><rdf:li>st|room</rdf:li><rdf:li>st|scaffold</rdf:li><rdf:li>st|tube</rdf:li><rdf:li>st|warehouse</rdf:li><rdf:li>st|water pipe</rdf:li></rdf:Bag></lr:hierarchicalSubject></rdf:Description>
|
||||
</rdf:RDF>
|
||||
</x:xmpmeta>
|
||||
7
test/example/example.jpg.xmp
Normal file
@@ -0,0 +1,7 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<x:xmpmeta x:xmptk="XMP Core 4.4.0-Exiv2" xmlns:x="adobe:ns:meta/">
|
||||
<rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
|
||||
<rdf:Description rdf:about="" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:exif="http://ns.adobe.com/exif/1.0/" xmlns:lr="http://ns.adobe.com/lightroom/1.0/" xmlns:xmp="http://ns.adobe.com/xap/1.0/" xmlns:xmpMM="http://ns.adobe.com/xap/1.0/mm/" xmpMM:DerivedFrom="example.jpg">
|
||||
<dc:subject><rdf:Bag><rdf:li>st</rdf:li><rdf:li>cloud</rdf:li><rdf:li>cloudy</rdf:li><rdf:li>evening sky</rdf:li><rdf:li>sea</rdf:li><rdf:li>sky</rdf:li><rdf:li>storm cloud</rdf:li><rdf:li>stormy</rdf:li><rdf:li>sun</rdf:li><rdf:li>sunset</rdf:li></rdf:Bag></dc:subject><lr:hierarchicalSubject><rdf:Bag><rdf:li>st|cloud</rdf:li><rdf:li>st|cloudy</rdf:li><rdf:li>st|evening sky</rdf:li><rdf:li>st|sea</rdf:li><rdf:li>st|sky</rdf:li><rdf:li>st|storm cloud</rdf:li><rdf:li>st|stormy</rdf:li><rdf:li>st|sun</rdf:li><rdf:li>st|sunset</rdf:li></rdf:Bag></lr:hierarchicalSubject></rdf:Description>
|
||||
</rdf:RDF>
|
||||
</x:xmpmeta>
|
||||
7
test/example/example.tif.xmp
Normal file
@@ -0,0 +1,7 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<x:xmpmeta x:xmptk="XMP Core 4.4.0-Exiv2" xmlns:x="adobe:ns:meta/">
|
||||
<rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
|
||||
<rdf:Description rdf:about="" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:exif="http://ns.adobe.com/exif/1.0/" xmlns:lr="http://ns.adobe.com/lightroom/1.0/" xmlns:xmp="http://ns.adobe.com/xap/1.0/" xmlns:xmpMM="http://ns.adobe.com/xap/1.0/mm/" xmpMM:DerivedFrom="example.tif">
|
||||
<dc:subject><rdf:Bag><rdf:li>st</rdf:li><rdf:li>cloud</rdf:li><rdf:li>cloudy</rdf:li><rdf:li>evening sky</rdf:li><rdf:li>sea</rdf:li><rdf:li>sky</rdf:li><rdf:li>storm cloud</rdf:li><rdf:li>stormy</rdf:li><rdf:li>sun</rdf:li><rdf:li>sunset</rdf:li></rdf:Bag></dc:subject><lr:hierarchicalSubject><rdf:Bag><rdf:li>st|cloud</rdf:li><rdf:li>st|cloudy</rdf:li><rdf:li>st|evening sky</rdf:li><rdf:li>st|sea</rdf:li><rdf:li>st|sky</rdf:li><rdf:li>st|storm cloud</rdf:li><rdf:li>st|stormy</rdf:li><rdf:li>st|sun</rdf:li><rdf:li>st|sunset</rdf:li></rdf:Bag></lr:hierarchicalSubject></rdf:Description>
|
||||
</rdf:RDF>
|
||||
</x:xmpmeta>
|
||||
@@ -1,467 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>example - LICENSE</title>
|
||||
<link rel="manifest" href="/.static/manifest.json">
|
||||
<link rel="preload" href="file:///home/user/git/github.com/greflm13/StaticGalleryBuilder/test/.static/global.css" as="style">
|
||||
<link rel="preload" href="file:///home/user/git/github.com/greflm13/StaticGalleryBuilder/test/.static/theme.css" as="style">
|
||||
<link rel="icon" type="image/x-icon" href="file:///home/user/git/github.com/greflm13/StaticGalleryBuilder/test/.static/favicon.ico">
|
||||
<link rel="stylesheet" href="file:///home/user/git/github.com/greflm13/StaticGalleryBuilder/test/.static/global.css">
|
||||
<link rel="stylesheet" href="file:///home/user/git/github.com/greflm13/StaticGalleryBuilder/test/.static/theme.css">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div class="header">
|
||||
<ul class="navbar">
|
||||
<li><a href="file:///home/user/git/github.com/greflm13/StaticGalleryBuilder/test/">Home</a></li>
|
||||
<li><a href="file:///home/user/git/github.com/greflm13/StaticGalleryBuilder/test/example/">Parent Directory</a></li>
|
||||
<li class="title"><span class="header">example - LICENSE</span></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="licensefile">
|
||||
Attribution-ShareAlike 4.0 International</br>
|
||||
</br>
|
||||
=======================================================================</br>
|
||||
</br>
|
||||
Creative Commons Corporation ("Creative Commons") is not a law firm and</br>
|
||||
does not provide legal services or legal advice. Distribution of</br>
|
||||
Creative Commons public licenses does not create a lawyer-client or</br>
|
||||
other relationship. Creative Commons makes its licenses and related</br>
|
||||
information available on an "as-is" basis. Creative Commons gives no</br>
|
||||
warranties regarding its licenses, any material licensed under their</br>
|
||||
terms and conditions, or any related information. Creative Commons</br>
|
||||
disclaims all liability for damages resulting from their use to the</br>
|
||||
fullest extent possible.</br>
|
||||
</br>
|
||||
Using Creative Commons Public Licenses</br>
|
||||
</br>
|
||||
Creative Commons public licenses provide a standard set of terms and</br>
|
||||
conditions that creators and other rights holders may use to share</br>
|
||||
original works of authorship and other material subject to copyright</br>
|
||||
and certain other rights specified in the public license below. The</br>
|
||||
following considerations are for informational purposes only, are not</br>
|
||||
exhaustive, and do not form part of our licenses.</br>
|
||||
</br>
|
||||
  Considerations for licensors: Our public licenses are</br>
|
||||
  intended for use by those authorized to give the public</br>
|
||||
  permission to use material in ways otherwise restricted by</br>
|
||||
  copyright and certain other rights. Our licenses are</br>
|
||||
  irrevocable. Licensors should read and understand the terms</br>
|
||||
  and conditions of the license they choose before applying it.</br>
|
||||
  Licensors should also secure all rights necessary before</br>
|
||||
  applying our licenses so that the public can reuse the</br>
|
||||
  material as expected. Licensors should clearly mark any</br>
|
||||
  material not subject to the license. This includes other CC-</br>
|
||||
  licensed material, or material used under an exception or</br>
|
||||
  limitation to copyright. More considerations for licensors:</br>
|
||||
 wiki.creativecommons.org/Considerations_for_licensors</br>
|
||||
</br>
|
||||
  Considerations for the public: By using one of our public</br>
|
||||
  licenses, a licensor grants the public permission to use the</br>
|
||||
  licensed material under specified terms and conditions. If</br>
|
||||
  the licensor's permission is not necessary for any reason--for</br>
|
||||
  example, because of any applicable exception or limitation to</br>
|
||||
  copyright--then that use is not regulated by the license. Our</br>
|
||||
  licenses grant only permissions under copyright and certain</br>
|
||||
  other rights that a licensor has authority to grant. Use of</br>
|
||||
  the licensed material may still be restricted for other</br>
|
||||
  reasons, including because others have copyright or other</br>
|
||||
  rights in the material. A licensor may make special requests,</br>
|
||||
  such as asking that all changes be marked or described.</br>
|
||||
  Although not required by our licenses, you are encouraged to</br>
|
||||
  respect those requests where reasonable. More considerations</br>
|
||||
  for the public:</br>
|
||||
 wiki.creativecommons.org/Considerations_for_licensees</br>
|
||||
</br>
|
||||
=======================================================================</br>
|
||||
</br>
|
||||
Creative Commons Attribution-ShareAlike 4.0 International Public</br>
|
||||
License</br>
|
||||
</br>
|
||||
By exercising the Licensed Rights (defined below), You accept and agree</br>
|
||||
to be bound by the terms and conditions of this Creative Commons</br>
|
||||
Attribution-ShareAlike 4.0 International Public License ("Public</br>
|
||||
License"). To the extent this Public License may be interpreted as a</br>
|
||||
contract, You are granted the Licensed Rights in consideration of Your</br>
|
||||
acceptance of these terms and conditions, and the Licensor grants You</br>
|
||||
such rights in consideration of benefits the Licensor receives from</br>
|
||||
making the Licensed Material available under these terms and</br>
|
||||
conditions.</br>
|
||||
</br>
|
||||
</br>
|
||||
Section 1 -- Definitions.</br>
|
||||
</br>
|
||||
 a. Adapted Material means material subject to Copyright and Similar</br>
|
||||
  Rights that is derived from or based upon the Licensed Material</br>
|
||||
  and in which the Licensed Material is translated, altered,</br>
|
||||
  arranged, transformed, or otherwise modified in a manner requiring</br>
|
||||
  permission under the Copyright and Similar Rights held by the</br>
|
||||
  Licensor. For purposes of this Public License, where the Licensed</br>
|
||||
  Material is a musical work, performance, or sound recording,</br>
|
||||
  Adapted Material is always produced where the Licensed Material is</br>
|
||||
  synched in timed relation with a moving image.</br>
|
||||
</br>
|
||||
 b. Adapter's License means the license You apply to Your Copyright</br>
|
||||
  and Similar Rights in Your contributions to Adapted Material in</br>
|
||||
  accordance with the terms and conditions of this Public License.</br>
|
||||
</br>
|
||||
 c. BY-SA Compatible License means a license listed at</br>
|
||||
  creativecommons.org/compatiblelicenses, approved by Creative</br>
|
||||
  Commons as essentially the equivalent of this Public License.</br>
|
||||
</br>
|
||||
 d. Copyright and Similar Rights means copyright and/or similar rights</br>
|
||||
  closely related to copyright including, without limitation,</br>
|
||||
  performance, broadcast, sound recording, and Sui Generis Database</br>
|
||||
  Rights, without regard to how the rights are labeled or</br>
|
||||
  categorized. For purposes of this Public License, the rights</br>
|
||||
  specified in Section 2(b)(1)-(2) are not Copyright and Similar</br>
|
||||
  Rights.</br>
|
||||
</br>
|
||||
 e. Effective Technological Measures means those measures that, in the</br>
|
||||
  absence of proper authority, may not be circumvented under laws</br>
|
||||
  fulfilling obligations under Article 11 of the WIPO Copyright</br>
|
||||
  Treaty adopted on December 20, 1996, and/or similar international</br>
|
||||
  agreements.</br>
|
||||
</br>
|
||||
 f. Exceptions and Limitations means fair use, fair dealing, and/or</br>
|
||||
  any other exception or limitation to Copyright and Similar Rights</br>
|
||||
  that applies to Your use of the Licensed Material.</br>
|
||||
</br>
|
||||
 g. License Elements means the license attributes listed in the name</br>
|
||||
  of a Creative Commons Public License. The License Elements of this</br>
|
||||
  Public License are Attribution and ShareAlike.</br>
|
||||
</br>
|
||||
 h. Licensed Material means the artistic or literary work, database,</br>
|
||||
  or other material to which the Licensor applied this Public</br>
|
||||
  License.</br>
|
||||
</br>
|
||||
 i. Licensed Rights means the rights granted to You subject to the</br>
|
||||
  terms and conditions of this Public License, which are limited to</br>
|
||||
  all Copyright and Similar Rights that apply to Your use of the</br>
|
||||
  Licensed Material and that the Licensor has authority to license.</br>
|
||||
</br>
|
||||
 j. Licensor means the individual(s) or entity(ies) granting rights</br>
|
||||
  under this Public License.</br>
|
||||
</br>
|
||||
 k. Share means to provide material to the public by any means or</br>
|
||||
  process that requires permission under the Licensed Rights, such</br>
|
||||
  as reproduction, public display, public performance, distribution,</br>
|
||||
  dissemination, communication, or importation, and to make material</br>
|
||||
  available to the public including in ways that members of the</br>
|
||||
  public may access the material from a place and at a time</br>
|
||||
  individually chosen by them.</br>
|
||||
</br>
|
||||
 l. Sui Generis Database Rights means rights other than copyright</br>
|
||||
  resulting from Directive 96/9/EC of the European Parliament and of</br>
|
||||
  the Council of 11 March 1996 on the legal protection of databases,</br>
|
||||
  as amended and/or succeeded, as well as other essentially</br>
|
||||
  equivalent rights anywhere in the world.</br>
|
||||
</br>
|
||||
 m. You means the individual or entity exercising the Licensed Rights</br>
|
||||
  under this Public License. Your has a corresponding meaning.</br>
|
||||
</br>
|
||||
</br>
|
||||
Section 2 -- Scope.</br>
|
||||
</br>
|
||||
 a. License grant.</br>
|
||||
</br>
|
||||
  1. Subject to the terms and conditions of this Public License,</br>
|
||||
   the Licensor hereby grants You a worldwide, royalty-free,</br>
|
||||
   non-sublicensable, non-exclusive, irrevocable license to</br>
|
||||
   exercise the Licensed Rights in the Licensed Material to:</br>
|
||||
</br>
|
||||
   a. reproduce and Share the Licensed Material, in whole or</br>
|
||||
    in part; and</br>
|
||||
</br>
|
||||
   b. produce, reproduce, and Share Adapted Material.</br>
|
||||
</br>
|
||||
  2. Exceptions and Limitations. For the avoidance of doubt, where</br>
|
||||
   Exceptions and Limitations apply to Your use, this Public</br>
|
||||
   License does not apply, and You do not need to comply with</br>
|
||||
   its terms and conditions.</br>
|
||||
</br>
|
||||
  3. Term. The term of this Public License is specified in Section</br>
|
||||
   6(a).</br>
|
||||
</br>
|
||||
  4. Media and formats; technical modifications allowed. The</br>
|
||||
   Licensor authorizes You to exercise the Licensed Rights in</br>
|
||||
   all media and formats whether now known or hereafter created,</br>
|
||||
   and to make technical modifications necessary to do so. The</br>
|
||||
   Licensor waives and/or agrees not to assert any right or</br>
|
||||
   authority to forbid You from making technical modifications</br>
|
||||
   necessary to exercise the Licensed Rights, including</br>
|
||||
   technical modifications necessary to circumvent Effective</br>
|
||||
   Technological Measures. For purposes of this Public License,</br>
|
||||
   simply making modifications authorized by this Section 2(a)</br>
|
||||
   (4) never produces Adapted Material.</br>
|
||||
</br>
|
||||
  5. Downstream recipients.</br>
|
||||
</br>
|
||||
   a. Offer from the Licensor -- Licensed Material. Every</br>
|
||||
    recipient of the Licensed Material automatically</br>
|
||||
    receives an offer from the Licensor to exercise the</br>
|
||||
    Licensed Rights under the terms and conditions of this</br>
|
||||
    Public License.</br>
|
||||
</br>
|
||||
   b. Additional offer from the Licensor -- Adapted Material.</br>
|
||||
    Every recipient of Adapted Material from You</br>
|
||||
    automatically receives an offer from the Licensor to</br>
|
||||
    exercise the Licensed Rights in the Adapted Material</br>
|
||||
    under the conditions of the Adapter's License You apply.</br>
|
||||
</br>
|
||||
   c. No downstream restrictions. You may not offer or impose</br>
|
||||
    any additional or different terms or conditions on, or</br>
|
||||
    apply any Effective Technological Measures to, the</br>
|
||||
    Licensed Material if doing so restricts exercise of the</br>
|
||||
    Licensed Rights by any recipient of the Licensed</br>
|
||||
    Material.</br>
|
||||
</br>
|
||||
  6. No endorsement. Nothing in this Public License constitutes or</br>
|
||||
   may be construed as permission to assert or imply that You</br>
|
||||
   are, or that Your use of the Licensed Material is, connected</br>
|
||||
   with, or sponsored, endorsed, or granted official status by,</br>
|
||||
   the Licensor or others designated to receive attribution as</br>
|
||||
   provided in Section 3(a)(1)(A)(i).</br>
|
||||
</br>
|
||||
 b. Other rights.</br>
|
||||
</br>
|
||||
  1. Moral rights, such as the right of integrity, are not</br>
|
||||
   licensed under this Public License, nor are publicity,</br>
|
||||
   privacy, and/or other similar personality rights; however, to</br>
|
||||
   the extent possible, the Licensor waives and/or agrees not to</br>
|
||||
   assert any such rights held by the Licensor to the limited</br>
|
||||
   extent necessary to allow You to exercise the Licensed</br>
|
||||
   Rights, but not otherwise.</br>
|
||||
</br>
|
||||
  2. Patent and trademark rights are not licensed under this</br>
|
||||
   Public License.</br>
|
||||
</br>
|
||||
  3. To the extent possible, the Licensor waives any right to</br>
|
||||
   collect royalties from You for the exercise of the Licensed</br>
|
||||
   Rights, whether directly or through a collecting society</br>
|
||||
   under any voluntary or waivable statutory or compulsory</br>
|
||||
   licensing scheme. In all other cases the Licensor expressly</br>
|
||||
   reserves any right to collect such royalties.</br>
|
||||
</br>
|
||||
</br>
|
||||
Section 3 -- License Conditions.</br>
|
||||
</br>
|
||||
Your exercise of the Licensed Rights is expressly made subject to the</br>
|
||||
following conditions.</br>
|
||||
</br>
|
||||
 a. Attribution.</br>
|
||||
</br>
|
||||
  1. If You Share the Licensed Material (including in modified</br>
|
||||
   form), You must:</br>
|
||||
</br>
|
||||
   a. retain the following if it is supplied by the Licensor</br>
|
||||
    with the Licensed Material:</br>
|
||||
</br>
|
||||
     i. identification of the creator(s) of the Licensed</br>
|
||||
     Material and any others designated to receive</br>
|
||||
     attribution, in any reasonable manner requested by</br>
|
||||
     the Licensor (including by pseudonym if</br>
|
||||
     designated);</br>
|
||||
</br>
|
||||
    ii. a copyright notice;</br>
|
||||
</br>
|
||||
    iii. a notice that refers to this Public License;</br>
|
||||
</br>
|
||||
    iv. a notice that refers to the disclaimer of</br>
|
||||
     warranties;</br>
|
||||
</br>
|
||||
     v. a URI or hyperlink to the Licensed Material to the</br>
|
||||
     extent reasonably practicable;</br>
|
||||
</br>
|
||||
   b. indicate if You modified the Licensed Material and</br>
|
||||
    retain an indication of any previous modifications; and</br>
|
||||
</br>
|
||||
   c. indicate the Licensed Material is licensed under this</br>
|
||||
    Public License, and include the text of, or the URI or</br>
|
||||
    hyperlink to, this Public License.</br>
|
||||
</br>
|
||||
  2. You may satisfy the conditions in Section 3(a)(1) in any</br>
|
||||
   reasonable manner based on the medium, means, and context in</br>
|
||||
   which You Share the Licensed Material. For example, it may be</br>
|
||||
   reasonable to satisfy the conditions by providing a URI or</br>
|
||||
   hyperlink to a resource that includes the required</br>
|
||||
   information.</br>
|
||||
</br>
|
||||
  3. If requested by the Licensor, You must remove any of the</br>
|
||||
   information required by Section 3(a)(1)(A) to the extent</br>
|
||||
   reasonably practicable.</br>
|
||||
</br>
|
||||
 b. ShareAlike.</br>
|
||||
</br>
|
||||
  In addition to the conditions in Section 3(a), if You Share</br>
|
||||
  Adapted Material You produce, the following conditions also apply.</br>
|
||||
</br>
|
||||
  1. The Adapter's License You apply must be a Creative Commons</br>
|
||||
   license with the same License Elements, this version or</br>
|
||||
   later, or a BY-SA Compatible License.</br>
|
||||
</br>
|
||||
  2. You must include the text of, or the URI or hyperlink to, the</br>
|
||||
   Adapter's License You apply. You may satisfy this condition</br>
|
||||
   in any reasonable manner based on the medium, means, and</br>
|
||||
   context in which You Share Adapted Material.</br>
|
||||
</br>
|
||||
  3. You may not offer or impose any additional or different terms</br>
|
||||
   or conditions on, or apply any Effective Technological</br>
|
||||
   Measures to, Adapted Material that restrict exercise of the</br>
|
||||
   rights granted under the Adapter's License You apply.</br>
|
||||
</br>
|
||||
</br>
|
||||
Section 4 -- Sui Generis Database Rights.</br>
|
||||
</br>
|
||||
Where the Licensed Rights include Sui Generis Database Rights that</br>
|
||||
apply to Your use of the Licensed Material:</br>
|
||||
</br>
|
||||
 a. for the avoidance of doubt, Section 2(a)(1) grants You the right</br>
|
||||
  to extract, reuse, reproduce, and Share all or a substantial</br>
|
||||
  portion of the contents of the database;</br>
|
||||
</br>
|
||||
 b. if You include all or a substantial portion of the database</br>
|
||||
  contents in a database in which You have Sui Generis Database</br>
|
||||
  Rights, then the database in which You have Sui Generis Database</br>
|
||||
  Rights (but not its individual contents) is Adapted Material,</br>
|
||||
  including for purposes of Section 3(b); and</br>
|
||||
</br>
|
||||
 c. You must comply with the conditions in Section 3(a) if You Share</br>
|
||||
  all or a substantial portion of the contents of the database.</br>
|
||||
</br>
|
||||
For the avoidance of doubt, this Section 4 supplements and does not</br>
|
||||
replace Your obligations under this Public License where the Licensed</br>
|
||||
Rights include other Copyright and Similar Rights.</br>
|
||||
</br>
|
||||
</br>
|
||||
Section 5 -- Disclaimer of Warranties and Limitation of Liability.</br>
|
||||
</br>
|
||||
 a. UNLESS OTHERWISE SEPARATELY UNDERTAKEN BY THE LICENSOR, TO THE</br>
|
||||
  EXTENT POSSIBLE, THE LICENSOR OFFERS THE LICENSED MATERIAL AS-IS</br>
|
||||
  AND AS-AVAILABLE, AND MAKES NO REPRESENTATIONS OR WARRANTIES OF</br>
|
||||
  ANY KIND CONCERNING THE LICENSED MATERIAL, WHETHER EXPRESS,</br>
|
||||
  IMPLIED, STATUTORY, OR OTHER. THIS INCLUDES, WITHOUT LIMITATION,</br>
|
||||
  WARRANTIES OF TITLE, MERCHANTABILITY, FITNESS FOR A PARTICULAR</br>
|
||||
  PURPOSE, NON-INFRINGEMENT, ABSENCE OF LATENT OR OTHER DEFECTS,</br>
|
||||
  ACCURACY, OR THE PRESENCE OR ABSENCE OF ERRORS, WHETHER OR NOT</br>
|
||||
  KNOWN OR DISCOVERABLE. WHERE DISCLAIMERS OF WARRANTIES ARE NOT</br>
|
||||
  ALLOWED IN FULL OR IN PART, THIS DISCLAIMER MAY NOT APPLY TO YOU.</br>
|
||||
</br>
|
||||
 b. TO THE EXTENT POSSIBLE, IN NO EVENT WILL THE LICENSOR BE LIABLE</br>
|
||||
  TO YOU ON ANY LEGAL THEORY (INCLUDING, WITHOUT LIMITATION,</br>
|
||||
  NEGLIGENCE) OR OTHERWISE FOR ANY DIRECT, SPECIAL, INDIRECT,</br>
|
||||
  INCIDENTAL, CONSEQUENTIAL, PUNITIVE, EXEMPLARY, OR OTHER LOSSES,</br>
|
||||
  COSTS, EXPENSES, OR DAMAGES ARISING OUT OF THIS PUBLIC LICENSE OR</br>
|
||||
  USE OF THE LICENSED MATERIAL, EVEN IF THE LICENSOR HAS BEEN</br>
|
||||
  ADVISED OF THE POSSIBILITY OF SUCH LOSSES, COSTS, EXPENSES, OR</br>
|
||||
  DAMAGES. WHERE A LIMITATION OF LIABILITY IS NOT ALLOWED IN FULL OR</br>
|
||||
  IN PART, THIS LIMITATION MAY NOT APPLY TO YOU.</br>
|
||||
</br>
|
||||
 c. The disclaimer of warranties and limitation of liability provided</br>
|
||||
  above shall be interpreted in a manner that, to the extent</br>
|
||||
  possible, most closely approximates an absolute disclaimer and</br>
|
||||
  waiver of all liability.</br>
|
||||
</br>
|
||||
</br>
|
||||
Section 6 -- Term and Termination.</br>
|
||||
</br>
|
||||
 a. This Public License applies for the term of the Copyright and</br>
|
||||
  Similar Rights licensed here. However, if You fail to comply with</br>
|
||||
  this Public License, then Your rights under this Public License</br>
|
||||
  terminate automatically.</br>
|
||||
</br>
|
||||
 b. Where Your right to use the Licensed Material has terminated under</br>
|
||||
  Section 6(a), it reinstates:</br>
|
||||
</br>
|
||||
  1. automatically as of the date the violation is cured, provided</br>
|
||||
   it is cured within 30 days of Your discovery of the</br>
|
||||
   violation; or</br>
|
||||
</br>
|
||||
  2. upon express reinstatement by the Licensor.</br>
|
||||
</br>
|
||||
  For the avoidance of doubt, this Section 6(b) does not affect any</br>
|
||||
  right the Licensor may have to seek remedies for Your violations</br>
|
||||
  of this Public License.</br>
|
||||
</br>
|
||||
 c. For the avoidance of doubt, the Licensor may also offer the</br>
|
||||
  Licensed Material under separate terms or conditions or stop</br>
|
||||
  distributing the Licensed Material at any time; however, doing so</br>
|
||||
  will not terminate this Public License.</br>
|
||||
</br>
|
||||
 d. Sections 1, 5, 6, 7, and 8 survive termination of this Public</br>
|
||||
  License.</br>
|
||||
</br>
|
||||
</br>
|
||||
Section 7 -- Other Terms and Conditions.</br>
|
||||
</br>
|
||||
 a. The Licensor shall not be bound by any additional or different</br>
|
||||
  terms or conditions communicated by You unless expressly agreed.</br>
|
||||
</br>
|
||||
 b. Any arrangements, understandings, or agreements regarding the</br>
|
||||
  Licensed Material not stated herein are separate from and</br>
|
||||
  independent of the terms and conditions of this Public License.</br>
|
||||
</br>
|
||||
</br>
|
||||
Section 8 -- Interpretation.</br>
|
||||
</br>
|
||||
 a. For the avoidance of doubt, this Public License does not, and</br>
|
||||
  shall not be interpreted to, reduce, limit, restrict, or impose</br>
|
||||
  conditions on any use of the Licensed Material that could lawfully</br>
|
||||
  be made without permission under this Public License.</br>
|
||||
</br>
|
||||
 b. To the extent possible, if any provision of this Public License is</br>
|
||||
  deemed unenforceable, it shall be automatically reformed to the</br>
|
||||
  minimum extent necessary to make it enforceable. If the provision</br>
|
||||
  cannot be reformed, it shall be severed from this Public License</br>
|
||||
  without affecting the enforceability of the remaining terms and</br>
|
||||
  conditions.</br>
|
||||
</br>
|
||||
 c. No term or condition of this Public License will be waived and no</br>
|
||||
  failure to comply consented to unless expressly agreed to by the</br>
|
||||
  Licensor.</br>
|
||||
</br>
|
||||
 d. Nothing in this Public License constitutes or may be interpreted</br>
|
||||
  as a limitation upon, or waiver of, any privileges and immunities</br>
|
||||
  that apply to the Licensor or You, including from the legal</br>
|
||||
  processes of any jurisdiction or authority.</br>
|
||||
</br>
|
||||
</br>
|
||||
=======================================================================</br>
|
||||
</br>
|
||||
Creative Commons is not a party to its public</br>
|
||||
licenses. Notwithstanding, Creative Commons may elect to apply one of</br>
|
||||
its public licenses to material it publishes and in those instances</br>
|
||||
will be considered the “Licensor.” The text of the Creative Commons</br>
|
||||
public licenses is dedicated to the public domain under the CC0 Public</br>
|
||||
Domain Dedication. Except for the limited purpose of indicating that</br>
|
||||
material is shared under a Creative Commons public license or as</br>
|
||||
otherwise permitted by the Creative Commons policies published at</br>
|
||||
creativecommons.org/policies, Creative Commons does not authorize the</br>
|
||||
use of the trademark "Creative Commons" or any other trademark or logo</br>
|
||||
of Creative Commons without its prior written consent including,</br>
|
||||
without limitation, in connection with any unauthorized modifications</br>
|
||||
to any of its public licenses or any other arrangements,</br>
|
||||
understandings, or agreements concerning use of licensed material. For</br>
|
||||
the avoidance of doubt, this paragraph does not form part of the</br>
|
||||
public licenses.</br>
|
||||
</br>
|
||||
Creative Commons may be contacted at creativecommons.org.</br>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="footer" xmlns:cc="http://creativecommons.org/ns#" xmlns:dct="http://purl.org/dc/terms/">
|
||||
<a property="dct:title" rel="cc:attributionURL" href="file:///home/user/git/github.com/greflm13/StaticGalleryBuilder/test/">Pictures</a> by <span property="cc:attributionName">Author</span> is licensed under
|
||||
<a href="https://creativecommons.org/licenses/by-nc-sa/4.0/" target="_blank" rel="license noopener noreferrer">CC BY-NC-SA 4.0
|
||||
<img src="https://mirrors.creativecommons.org/presskit/icons/cc.svg" alt="" />
|
||||
<img src="https://mirrors.creativecommons.org/presskit/icons/by.svg" alt="" />
|
||||
<img src="https://mirrors.creativecommons.org/presskit/icons/nc.svg" alt="" />
|
||||
<img src="https://mirrors.creativecommons.org/presskit/icons/sa.svg" alt="" />
|
||||
</a>
|
||||
<span class="attribution">Made with <a href="https://github.com/greflm13/StaticGalleryBuilder" target="_blank" rel="noopener noreferrer">StaticGalleryBuilder 2.5.0</a> by <a
|
||||
href="https://github.com/greflm13" target="_blank" rel="noopener noreferrer"><svg width="48.858002mm" height="21.24mm" viewBox="0 0 48.858002 21.24" version="1.1" id="svg1" xmlns="http://www.w3.org/2000/svg" xmlns:svg="http://www.w3.org/2000/svg"> <text xml:space="preserve" x="21.124891" y="17.106812" font-style="normal" font-variant="normal" font-weight="300" font-stretch="condensed" font-size="2.46944px" line-height="9.33327px" font-family="Barlow Condensed Light" fill="#6e6e6e" stroke-width="1" fill-opacity="1">sorogon</text> <text xml:space="preserve" x="2.3734004" y="14.853325" font-style="normal" font-variant="normal" font-weight="250" font-stretch="condensed" font-size="16.9333px" line-height="63.9997px" font-family="Barlow Condensed Thin" fill="#6e6e6e" stroke-width="1" fill-opacity="1"></srgn></text> </svg></a>.</span>
|
||||
<button onclick="topFunction()" id="totop" title="Back to Top">Back to Top</button>
|
||||
</div>
|
||||
</body>
|
||||
@@ -97,6 +97,10 @@ body {
|
||||
background-color: var(--color6);
|
||||
}
|
||||
|
||||
.tagentry > label:hover {
|
||||
background-color: var(--color3);
|
||||
}
|
||||
|
||||
.column img {
|
||||
background-color: var(--bcolor2);
|
||||
}
|
||||
|
||||
@@ -96,6 +96,10 @@ body {
|
||||
background-color: var(--color3);
|
||||
}
|
||||
|
||||
.tagentry > label:hover {
|
||||
background-color: var(--color7);
|
||||
}
|
||||
|
||||
.column img {
|
||||
background-color: var(--bcolor1);
|
||||
}
|
||||
|
||||
@@ -74,6 +74,10 @@
|
||||
background-color: var(--bcolor1);
|
||||
}
|
||||
|
||||
.tagentry > label:hover {
|
||||
background-color: var(--bcolor3);
|
||||
}
|
||||
|
||||
.column img {
|
||||
background-color: var(--bcolor1);
|
||||
}
|
||||
|
||||
@@ -74,6 +74,10 @@
|
||||
background-color: var(--bcolor1);
|
||||
}
|
||||
|
||||
.tagentry > label:hover {
|
||||
background-color: var(--bcolor3);
|
||||
}
|
||||
|
||||
.column img {
|
||||
background-color: var(--bcolor1);
|
||||
}
|
||||
|
||||
@@ -79,6 +79,10 @@
|
||||
font-family: "Playfair Display", serif;
|
||||
}
|
||||
|
||||
.tagentry > label:hover {
|
||||
background-color: var(--color3);
|
||||
}
|
||||
|
||||
.column img {
|
||||
background-color: var(--bcolor4);
|
||||
}
|
||||
|
||||
@@ -73,6 +73,10 @@
|
||||
background-color: var(--bcolor2);
|
||||
}
|
||||
|
||||
.tagentry > label:hover {
|
||||
background-color: var(--bcolor4);
|
||||
}
|
||||
|
||||
.column img {
|
||||
background-color: var(--bcolor4);
|
||||
}
|
||||
|
||||
@@ -79,6 +79,10 @@
|
||||
font-family: "Nunito", sans-serif;
|
||||
}
|
||||
|
||||
.tagentry > label:hover {
|
||||
background-color: var(--color4);
|
||||
}
|
||||
|
||||
.column img {
|
||||
background-color: var(--bcolor4);
|
||||
}
|
||||
|
||||
@@ -73,6 +73,10 @@
|
||||
background-color: var(--bcolor2);
|
||||
}
|
||||
|
||||
.tagentry > label:hover {
|
||||
background-color: var(--bcolor4);
|
||||
}
|
||||
|
||||
.column img {
|
||||
background-color: var(--bcolor4);
|
||||
}
|
||||
|
||||
@@ -52,6 +52,10 @@
|
||||
background-color: var(--color3);
|
||||
}
|
||||
|
||||
.tagentry > label:hover {
|
||||
background-color: var(--color4);
|
||||
}
|
||||
|
||||
.column img {
|
||||
background-color: var(--bcolor2);
|
||||
}
|
||||
|
||||
@@ -52,6 +52,10 @@
|
||||
background-color: var(--color2);
|
||||
}
|
||||
|
||||
.tagentry > label:hover {
|
||||
background-color: var(--color4);
|
||||
}
|
||||
|
||||
.column img {
|
||||
background-color: var(--color2);
|
||||
}
|
||||
|
||||
@@ -73,6 +73,10 @@
|
||||
background-color: var(--bcolor2);
|
||||
}
|
||||
|
||||
.tagentry > label:hover {
|
||||
background-color: var(--bcolor4);
|
||||
}
|
||||
|
||||
.column img {
|
||||
background-color: var(--bcolor4);
|
||||
}
|
||||
|
||||
@@ -72,6 +72,10 @@
|
||||
background-color: var(--color3);
|
||||
}
|
||||
|
||||
.tagentry > label:hover {
|
||||
background-color: var(--color2);
|
||||
}
|
||||
|
||||
.column img {
|
||||
background-color: var(--bcolor3);
|
||||
}
|
||||
|
||||
@@ -55,6 +55,10 @@
|
||||
background-color: var(--bcolor2);
|
||||
}
|
||||
|
||||
.tagentry > label:hover {
|
||||
background-color: var(--bcolor3);
|
||||
}
|
||||
|
||||
.column img {
|
||||
background-color: var(--bcolor5);
|
||||
}
|
||||
|
||||
@@ -76,6 +76,10 @@
|
||||
background-color: var(--bcolor2);
|
||||
}
|
||||
|
||||
.tagentry > label:hover {
|
||||
background-color: var(--bcolor4);
|
||||
}
|
||||
|
||||
.column img {
|
||||
background-color: var(--bcolor5);
|
||||
}
|
||||
|
||||
|
Before Width: | Height: | Size: 1.3 MiB After Width: | Height: | Size: 1.1 MiB |
|
Before Width: | Height: | Size: 1.3 MiB After Width: | Height: | Size: 1.1 MiB |
|
Before Width: | Height: | Size: 1.3 MiB After Width: | Height: | Size: 1.0 MiB |
|
Before Width: | Height: | Size: 1.3 MiB After Width: | Height: | Size: 1.1 MiB |
|
Before Width: | Height: | Size: 1.3 MiB After Width: | Height: | Size: 1.1 MiB |
|
Before Width: | Height: | Size: 1.3 MiB After Width: | Height: | Size: 1.1 MiB |
|
Before Width: | Height: | Size: 1.3 MiB After Width: | Height: | Size: 1.1 MiB |
|
Before Width: | Height: | Size: 1.3 MiB After Width: | Height: | Size: 1.1 MiB |
|
Before Width: | Height: | Size: 1.3 MiB After Width: | Height: | Size: 1.1 MiB |
|
Before Width: | Height: | Size: 1.3 MiB After Width: | Height: | Size: 1.1 MiB |
|
Before Width: | Height: | Size: 1.3 MiB After Width: | Height: | Size: 1.1 MiB |
|
Before Width: | Height: | Size: 1.3 MiB After Width: | Height: | Size: 1.1 MiB |
|
Before Width: | Height: | Size: 1.3 MiB After Width: | Height: | Size: 1.1 MiB |
|
Before Width: | Height: | Size: 1.3 MiB After Width: | Height: | Size: 1.1 MiB |
|
Before Width: | Height: | Size: 1.3 MiB After Width: | Height: | Size: 1.1 MiB |
|
Before Width: | Height: | Size: 1.3 MiB After Width: | Height: | Size: 1.0 MiB |
|
Before Width: | Height: | Size: 1.3 MiB After Width: | Height: | Size: 1.1 MiB |
|
Before Width: | Height: | Size: 1.3 MiB After Width: | Height: | Size: 1.1 MiB |
|
Before Width: | Height: | Size: 1.3 MiB After Width: | Height: | Size: 1.1 MiB |
@@ -79,6 +79,10 @@
|
||||
font-family: "Lora", serif;
|
||||
}
|
||||
|
||||
.tagentry > label:hover {
|
||||
background-color: var(--bcolor3);
|
||||
}
|
||||
|
||||
.column img {
|
||||
background-color: var(--bcolor4);
|
||||
}
|
||||
|
||||
@@ -80,6 +80,10 @@
|
||||
background-color: var(--color4);
|
||||
}
|
||||
|
||||
.tagentry > label:hover {
|
||||
background-color: var(--color3);
|
||||
}
|
||||
|
||||
.column img {
|
||||
background-color: var(--color4);
|
||||
}
|
||||
|
||||
@@ -80,6 +80,11 @@
|
||||
font-family: "Roboto", sans-serif;
|
||||
}
|
||||
|
||||
.tagentry > label:hover {
|
||||
background-color: var(--bcolor3);
|
||||
color: var(--bcolor2);
|
||||
}
|
||||
|
||||
.column img {
|
||||
background-color: var(--bcolor4);
|
||||
}
|
||||
|
||||
@@ -74,6 +74,10 @@
|
||||
background-color: var(--bcolor2);
|
||||
}
|
||||
|
||||
.tagentry > label:hover {
|
||||
background-color: var(--bcolor4);
|
||||
}
|
||||
|
||||
.column img {
|
||||
background-color: var(--bcolor4);
|
||||
}
|
||||
|
||||
@@ -88,6 +88,10 @@
|
||||
font-family: "Montserrat", sans-serif;
|
||||
}
|
||||
|
||||
.tagentry > label:hover {
|
||||
background-color: var(--color2);
|
||||
}
|
||||
|
||||
.column img {
|
||||
background-color: var(--bcolor4);
|
||||
}
|
||||
|
||||