17 Commits

41 changed files with 928 additions and 262 deletions

View File

@@ -1 +1 @@
2.7.2 2.8.2

View File

@@ -55,6 +55,7 @@ The script supports several command-line options to customize its behavior. Belo
- `--ignore-other-files`: Ignore files that do not match the specified extensions. - `--ignore-other-files`: Ignore files that do not match the specified extensions.
- `--regenerate-thumbnails`: Regenerate thumbnails even if they already exist. - `--regenerate-thumbnails`: Regenerate thumbnails even if they already exist.
- `--reread-metadata`: Reread image metadata if it already exists. - `--reread-metadata`: Reread image metadata if it already exists.
- `--reread-sidecar`: Reread sidecar file data.
- `--reverse-sort`: Sort images by reverse name order. - `--reverse-sort`: Sort images by reverse name order.
- `--theme-path PATH`: Specify the path to the CSS theme file. Default is the provided default theme. - `--theme-path PATH`: Specify the path to the CSS theme file. Default is the provided default theme.
- `--use-fancy-folders`: Enable fancy folder view instead of the default Apache directory listing. - `--use-fancy-folders`: Enable fancy folder view instead of the default Apache directory listing.

View File

@@ -38,8 +38,8 @@
"-n", "-n",
"-m", "-m",
"--reverse-sort", "--reverse-sort",
// "--regenerate-thumbnails", "--regenerate-thumbnails",
// "--reread-metadata", "--reread-metadata",
"--folderthumbnails" "--folderthumbnails"
], ],
"console": "integratedTerminal", "console": "integratedTerminal",
@@ -90,8 +90,7 @@
"Scans", "Scans",
"--exclude-folder", "--exclude-folder",
"*/Galleries/*", "*/Galleries/*",
"--folderthumbnails", "--folderthumbnails"
"--reread-metadata"
], ],
"console": "integratedTerminal", "console": "integratedTerminal",
"name": "production", "name": "production",
@@ -257,6 +256,21 @@
"showReuseMessage": false, "showReuseMessage": false,
"clear": true "clear": true
} }
},
{
"command": "COLUMNS=120 ./builder.py --generate-help-preview help.svg",
"isBackground": false,
"label": "Create help svg",
"problemMatcher": [],
"type": "shell",
"presentation": {
"echo": false,
"reveal": "always",
"focus": true,
"panel": "dedicated",
"showReuseMessage": false,
"clear": true
}
} }
] ]
} }

View File

@@ -157,10 +157,31 @@ figure {
cursor: pointer; cursor: pointer;
} }
.tooltip .tooltiptext { .tooltip a {
display: none; cursor: pointer;
}
.tagtoggle {
cursor: pointer;
float: right;
padding: 12px;
}
.tagflex {
display: flex;
}
.tag {
flex: 1;
}
input {
pointer-events: none;
}
.tooltiptext {
cursor: default; cursor: default;
width: max-content;
position: absolute; position: absolute;
z-index: 100; z-index: 100;
opacity: 0; opacity: 0;
@@ -172,33 +193,66 @@ figure {
.tooltip .infotext { .tooltip .infotext {
padding: 12px; padding: 12px;
width: max-content;
} }
.tooltip .tagdropdown { .tooltiptext.tagdropdown {
width: max-content;
right: 0;
padding: 0; padding: 0;
margin: 0;
overflow: hidden;
transition: max-height 0.3s ease, opacity 0.3s ease;
max-height: 0;
opacity: 0;
} }
.tooltip:hover .tooltiptext { .tooltiptext.tagdropdown.show {
max-height: 286px;
overflow-y: scroll;
opacity: 1;
}
.tooltip:hover .infotext {
display: block; display: block;
opacity: 1; opacity: 1;
} }
.tooltip:active .tooltiptext { .tooltip:active .infotext {
display: block; display: block;
opacity: 1; opacity: 1;
} }
.tooltip .tooltiptext .tagentry { .tagentryparent {
width: 100%;
overflow: hidden;
transition: max-height 0.3s ease, opacity 0.3s ease;
max-height: 0;
opacity: 0;
}
.tagentryparent.show {
max-height: 286px;
opacity: 1;
overflow-y: scroll;
}
.tagentry {
list-style: none; list-style: none;
width: 100%; width: 100%;
cursor: pointer; cursor: pointer;
margin: 0; margin: 0;
padding: 0; padding: 0;
display: block;
}
.tooltip .tooltiptext ol {
margin-left: 0;
padding-left: 0.5em;
} }
.tooltip .tooltiptext .tagentry label { .tooltip .tooltiptext .tagentry label {
cursor: pointer; cursor: pointer;
width: 100%;
height: 100%; height: 100%;
padding: 12px; padding: 12px;
display: block; display: block;

168
help.svg
View File

@@ -1,4 +1,4 @@
<svg class="rich-terminal" viewBox="0 0 1482 855.1999999999999" xmlns="http://www.w3.org/2000/svg"> <svg class="rich-terminal" viewBox="0 0 1482 928.4" xmlns="http://www.w3.org/2000/svg">
<!-- Generated with Rich https://www.textualize.io --> <!-- Generated with Rich https://www.textualize.io -->
<style> <style>
@@ -19,171 +19,183 @@
font-weight: 700; font-weight: 700;
} }
.terminal-1308707172-matrix { .terminal-3378394567-matrix {
font-family: Fira Code, monospace; font-family: Fira Code, monospace;
font-size: 20px; font-size: 20px;
line-height: 24.4px; line-height: 24.4px;
font-variant-east-asian: full-width; font-variant-east-asian: full-width;
} }
.terminal-1308707172-title { .terminal-3378394567-title {
font-size: 18px; font-size: 18px;
font-weight: bold; font-weight: bold;
font-family: arial; font-family: arial;
} }
.terminal-1308707172-r1 { fill: #ff8700 } .terminal-3378394567-r1 { fill: #ff8700 }
.terminal-1308707172-r2 { fill: #c5c8c6 } .terminal-3378394567-r2 { fill: #c5c8c6 }
.terminal-1308707172-r3 { fill: #808080 } .terminal-3378394567-r3 { fill: #808080 }
.terminal-1308707172-r4 { fill: #68a0b3 } .terminal-3378394567-r4 { fill: #68a0b3 }
.terminal-1308707172-r5 { fill: #00af87 } .terminal-3378394567-r5 { fill: #00af87 }
</style> </style>
<defs> <defs>
<clipPath id="terminal-1308707172-clip-terminal"> <clipPath id="terminal-3378394567-clip-terminal">
<rect x="0" y="0" width="1463.0" height="804.1999999999999" /> <rect x="0" y="0" width="1463.0" height="877.4" />
</clipPath> </clipPath>
<clipPath id="terminal-1308707172-line-0"> <clipPath id="terminal-3378394567-line-0">
<rect x="0" y="1.5" width="1464" height="24.65"/> <rect x="0" y="1.5" width="1464" height="24.65"/>
</clipPath> </clipPath>
<clipPath id="terminal-1308707172-line-1"> <clipPath id="terminal-3378394567-line-1">
<rect x="0" y="25.9" width="1464" height="24.65"/> <rect x="0" y="25.9" width="1464" height="24.65"/>
</clipPath> </clipPath>
<clipPath id="terminal-1308707172-line-2"> <clipPath id="terminal-3378394567-line-2">
<rect x="0" y="50.3" width="1464" height="24.65"/> <rect x="0" y="50.3" width="1464" height="24.65"/>
</clipPath> </clipPath>
<clipPath id="terminal-1308707172-line-3"> <clipPath id="terminal-3378394567-line-3">
<rect x="0" y="74.7" width="1464" height="24.65"/> <rect x="0" y="74.7" width="1464" height="24.65"/>
</clipPath> </clipPath>
<clipPath id="terminal-1308707172-line-4"> <clipPath id="terminal-3378394567-line-4">
<rect x="0" y="99.1" width="1464" height="24.65"/> <rect x="0" y="99.1" width="1464" height="24.65"/>
</clipPath> </clipPath>
<clipPath id="terminal-1308707172-line-5"> <clipPath id="terminal-3378394567-line-5">
<rect x="0" y="123.5" width="1464" height="24.65"/> <rect x="0" y="123.5" width="1464" height="24.65"/>
</clipPath> </clipPath>
<clipPath id="terminal-1308707172-line-6"> <clipPath id="terminal-3378394567-line-6">
<rect x="0" y="147.9" width="1464" height="24.65"/> <rect x="0" y="147.9" width="1464" height="24.65"/>
</clipPath> </clipPath>
<clipPath id="terminal-1308707172-line-7"> <clipPath id="terminal-3378394567-line-7">
<rect x="0" y="172.3" width="1464" height="24.65"/> <rect x="0" y="172.3" width="1464" height="24.65"/>
</clipPath> </clipPath>
<clipPath id="terminal-1308707172-line-8"> <clipPath id="terminal-3378394567-line-8">
<rect x="0" y="196.7" width="1464" height="24.65"/> <rect x="0" y="196.7" width="1464" height="24.65"/>
</clipPath> </clipPath>
<clipPath id="terminal-1308707172-line-9"> <clipPath id="terminal-3378394567-line-9">
<rect x="0" y="221.1" width="1464" height="24.65"/> <rect x="0" y="221.1" width="1464" height="24.65"/>
</clipPath> </clipPath>
<clipPath id="terminal-1308707172-line-10"> <clipPath id="terminal-3378394567-line-10">
<rect x="0" y="245.5" width="1464" height="24.65"/> <rect x="0" y="245.5" width="1464" height="24.65"/>
</clipPath> </clipPath>
<clipPath id="terminal-1308707172-line-11"> <clipPath id="terminal-3378394567-line-11">
<rect x="0" y="269.9" width="1464" height="24.65"/> <rect x="0" y="269.9" width="1464" height="24.65"/>
</clipPath> </clipPath>
<clipPath id="terminal-1308707172-line-12"> <clipPath id="terminal-3378394567-line-12">
<rect x="0" y="294.3" width="1464" height="24.65"/> <rect x="0" y="294.3" width="1464" height="24.65"/>
</clipPath> </clipPath>
<clipPath id="terminal-1308707172-line-13"> <clipPath id="terminal-3378394567-line-13">
<rect x="0" y="318.7" width="1464" height="24.65"/> <rect x="0" y="318.7" width="1464" height="24.65"/>
</clipPath> </clipPath>
<clipPath id="terminal-1308707172-line-14"> <clipPath id="terminal-3378394567-line-14">
<rect x="0" y="343.1" width="1464" height="24.65"/> <rect x="0" y="343.1" width="1464" height="24.65"/>
</clipPath> </clipPath>
<clipPath id="terminal-1308707172-line-15"> <clipPath id="terminal-3378394567-line-15">
<rect x="0" y="367.5" width="1464" height="24.65"/> <rect x="0" y="367.5" width="1464" height="24.65"/>
</clipPath> </clipPath>
<clipPath id="terminal-1308707172-line-16"> <clipPath id="terminal-3378394567-line-16">
<rect x="0" y="391.9" width="1464" height="24.65"/> <rect x="0" y="391.9" width="1464" height="24.65"/>
</clipPath> </clipPath>
<clipPath id="terminal-1308707172-line-17"> <clipPath id="terminal-3378394567-line-17">
<rect x="0" y="416.3" width="1464" height="24.65"/> <rect x="0" y="416.3" width="1464" height="24.65"/>
</clipPath> </clipPath>
<clipPath id="terminal-1308707172-line-18"> <clipPath id="terminal-3378394567-line-18">
<rect x="0" y="440.7" width="1464" height="24.65"/> <rect x="0" y="440.7" width="1464" height="24.65"/>
</clipPath> </clipPath>
<clipPath id="terminal-1308707172-line-19"> <clipPath id="terminal-3378394567-line-19">
<rect x="0" y="465.1" width="1464" height="24.65"/> <rect x="0" y="465.1" width="1464" height="24.65"/>
</clipPath> </clipPath>
<clipPath id="terminal-1308707172-line-20"> <clipPath id="terminal-3378394567-line-20">
<rect x="0" y="489.5" width="1464" height="24.65"/> <rect x="0" y="489.5" width="1464" height="24.65"/>
</clipPath> </clipPath>
<clipPath id="terminal-1308707172-line-21"> <clipPath id="terminal-3378394567-line-21">
<rect x="0" y="513.9" width="1464" height="24.65"/> <rect x="0" y="513.9" width="1464" height="24.65"/>
</clipPath> </clipPath>
<clipPath id="terminal-1308707172-line-22"> <clipPath id="terminal-3378394567-line-22">
<rect x="0" y="538.3" width="1464" height="24.65"/> <rect x="0" y="538.3" width="1464" height="24.65"/>
</clipPath> </clipPath>
<clipPath id="terminal-1308707172-line-23"> <clipPath id="terminal-3378394567-line-23">
<rect x="0" y="562.7" width="1464" height="24.65"/> <rect x="0" y="562.7" width="1464" height="24.65"/>
</clipPath> </clipPath>
<clipPath id="terminal-1308707172-line-24"> <clipPath id="terminal-3378394567-line-24">
<rect x="0" y="587.1" width="1464" height="24.65"/> <rect x="0" y="587.1" width="1464" height="24.65"/>
</clipPath> </clipPath>
<clipPath id="terminal-1308707172-line-25"> <clipPath id="terminal-3378394567-line-25">
<rect x="0" y="611.5" width="1464" height="24.65"/> <rect x="0" y="611.5" width="1464" height="24.65"/>
</clipPath> </clipPath>
<clipPath id="terminal-1308707172-line-26"> <clipPath id="terminal-3378394567-line-26">
<rect x="0" y="635.9" width="1464" height="24.65"/> <rect x="0" y="635.9" width="1464" height="24.65"/>
</clipPath> </clipPath>
<clipPath id="terminal-1308707172-line-27"> <clipPath id="terminal-3378394567-line-27">
<rect x="0" y="660.3" width="1464" height="24.65"/> <rect x="0" y="660.3" width="1464" height="24.65"/>
</clipPath> </clipPath>
<clipPath id="terminal-1308707172-line-28"> <clipPath id="terminal-3378394567-line-28">
<rect x="0" y="684.7" width="1464" height="24.65"/> <rect x="0" y="684.7" width="1464" height="24.65"/>
</clipPath> </clipPath>
<clipPath id="terminal-1308707172-line-29"> <clipPath id="terminal-3378394567-line-29">
<rect x="0" y="709.1" width="1464" height="24.65"/> <rect x="0" y="709.1" width="1464" height="24.65"/>
</clipPath> </clipPath>
<clipPath id="terminal-1308707172-line-30"> <clipPath id="terminal-3378394567-line-30">
<rect x="0" y="733.5" width="1464" height="24.65"/> <rect x="0" y="733.5" width="1464" height="24.65"/>
</clipPath> </clipPath>
<clipPath id="terminal-1308707172-line-31"> <clipPath id="terminal-3378394567-line-31">
<rect x="0" y="757.9" width="1464" height="24.65"/> <rect x="0" y="757.9" width="1464" height="24.65"/>
</clipPath> </clipPath>
<clipPath id="terminal-3378394567-line-32">
<rect x="0" y="782.3" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-3378394567-line-33">
<rect x="0" y="806.7" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-3378394567-line-34">
<rect x="0" y="831.1" width="1464" height="24.65"/>
</clipPath>
</defs> </defs>
<rect fill="#292929" stroke="rgba(255,255,255,0.35)" stroke-width="1" x="1" y="1" width="1480" height="853.2" rx="8"/> <rect fill="#292929" stroke="rgba(255,255,255,0.35)" stroke-width="1" x="1" y="1" width="1480" height="926.4" rx="8"/>
<g transform="translate(26,22)"> <g transform="translate(26,22)">
<circle cx="0" cy="0" r="7" fill="#ff5f57"/> <circle cx="0" cy="0" r="7" fill="#ff5f57"/>
<circle cx="22" cy="0" r="7" fill="#febc2e"/> <circle cx="22" cy="0" r="7" fill="#febc2e"/>
<circle cx="44" cy="0" r="7" fill="#28c840"/> <circle cx="44" cy="0" r="7" fill="#28c840"/>
</g> </g>
<g transform="translate(9, 41)" clip-path="url(#terminal-1308707172-clip-terminal)"> <g transform="translate(9, 41)" clip-path="url(#terminal-3378394567-clip-terminal)">
<g class="terminal-1308707172-matrix"> <g class="terminal-3378394567-matrix">
<text class="terminal-1308707172-r1" x="0" y="20" textLength="73.2" clip-path="url(#terminal-1308707172-line-0)">Usage:</text><text class="terminal-1308707172-r3" x="85.4" y="20" textLength="122" clip-path="url(#terminal-1308707172-line-0)">builder.py</text><text class="terminal-1308707172-r2" x="207.4" y="20" textLength="24.4" clip-path="url(#terminal-1308707172-line-0)">&#160;[</text><text class="terminal-1308707172-r4" x="231.8" y="20" textLength="24.4" clip-path="url(#terminal-1308707172-line-0)">-h</text><text class="terminal-1308707172-r2" x="256.2" y="20" textLength="36.6" clip-path="url(#terminal-1308707172-line-0)">]&#160;[</text><text class="terminal-1308707172-r4" x="292.8" y="20" textLength="24.4" clip-path="url(#terminal-1308707172-line-0)">-a</text><text class="terminal-1308707172-r5" x="329.4" y="20" textLength="73.2" clip-path="url(#terminal-1308707172-line-0)">AUTHOR</text><text class="terminal-1308707172-r2" x="402.6" y="20" textLength="36.6" clip-path="url(#terminal-1308707172-line-0)">]&#160;[</text><text class="terminal-1308707172-r4" x="439.2" y="20" textLength="24.4" clip-path="url(#terminal-1308707172-line-0)">-e</text><text class="terminal-1308707172-r5" x="475.8" y="20" textLength="109.8" clip-path="url(#terminal-1308707172-line-0)">EXTENSION</text><text class="terminal-1308707172-r2" x="585.6" y="20" textLength="36.6" clip-path="url(#terminal-1308707172-line-0)">]&#160;[</text><text class="terminal-1308707172-r4" x="622.2" y="20" textLength="24.4" clip-path="url(#terminal-1308707172-line-0)">-l</text><text class="terminal-1308707172-r5" x="658.8" y="20" textLength="85.4" clip-path="url(#terminal-1308707172-line-0)">LICENSE</text><text class="terminal-1308707172-r2" x="744.2" y="20" textLength="36.6" clip-path="url(#terminal-1308707172-line-0)">]&#160;[</text><text class="terminal-1308707172-r4" x="780.8" y="20" textLength="24.4" clip-path="url(#terminal-1308707172-line-0)">-m</text><text class="terminal-1308707172-r2" x="805.2" y="20" textLength="36.6" clip-path="url(#terminal-1308707172-line-0)">]&#160;[</text><text class="terminal-1308707172-r4" x="841.8" y="20" textLength="24.4" clip-path="url(#terminal-1308707172-line-0)">-n</text><text class="terminal-1308707172-r2" x="866.2" y="20" textLength="24.4" clip-path="url(#terminal-1308707172-line-0)">]&#160;</text><text class="terminal-1308707172-r4" x="890.6" y="20" textLength="24.4" clip-path="url(#terminal-1308707172-line-0)">-p</text><text class="terminal-1308707172-r5" x="927.2" y="20" textLength="48.8" clip-path="url(#terminal-1308707172-line-0)">ROOT</text><text class="terminal-1308707172-r4" x="988.2" y="20" textLength="24.4" clip-path="url(#terminal-1308707172-line-0)">-t</text><text class="terminal-1308707172-r5" x="1024.8" y="20" textLength="61" clip-path="url(#terminal-1308707172-line-0)">TITLE</text><text class="terminal-1308707172-r4" x="1098" y="20" textLength="24.4" clip-path="url(#terminal-1308707172-line-0)">-w</text><text class="terminal-1308707172-r5" x="1134.6" y="20" textLength="36.6" clip-path="url(#terminal-1308707172-line-0)">URL</text><text class="terminal-1308707172-r2" x="1464" y="20" textLength="12.2" clip-path="url(#terminal-1308707172-line-0)"> <text class="terminal-3378394567-r1" x="0" y="20" textLength="73.2" clip-path="url(#terminal-3378394567-line-0)">Usage:</text><text class="terminal-3378394567-r3" x="85.4" y="20" textLength="122" clip-path="url(#terminal-3378394567-line-0)">builder.py</text><text class="terminal-3378394567-r2" x="207.4" y="20" textLength="24.4" clip-path="url(#terminal-3378394567-line-0)">&#160;[</text><text class="terminal-3378394567-r4" x="231.8" y="20" textLength="24.4" clip-path="url(#terminal-3378394567-line-0)">-h</text><text class="terminal-3378394567-r2" x="256.2" y="20" textLength="36.6" clip-path="url(#terminal-3378394567-line-0)">]&#160;[</text><text class="terminal-3378394567-r4" x="292.8" y="20" textLength="24.4" clip-path="url(#terminal-3378394567-line-0)">-a</text><text class="terminal-3378394567-r5" x="329.4" y="20" textLength="73.2" clip-path="url(#terminal-3378394567-line-0)">AUTHOR</text><text class="terminal-3378394567-r2" x="402.6" y="20" textLength="36.6" clip-path="url(#terminal-3378394567-line-0)">]&#160;[</text><text class="terminal-3378394567-r4" x="439.2" y="20" textLength="24.4" clip-path="url(#terminal-3378394567-line-0)">-e</text><text class="terminal-3378394567-r5" x="475.8" y="20" textLength="109.8" clip-path="url(#terminal-3378394567-line-0)">EXTENSION</text><text class="terminal-3378394567-r2" x="585.6" y="20" textLength="36.6" clip-path="url(#terminal-3378394567-line-0)">]&#160;[</text><text class="terminal-3378394567-r4" x="622.2" y="20" textLength="24.4" clip-path="url(#terminal-3378394567-line-0)">-l</text><text class="terminal-3378394567-r5" x="658.8" y="20" textLength="85.4" clip-path="url(#terminal-3378394567-line-0)">LICENSE</text><text class="terminal-3378394567-r2" x="744.2" y="20" textLength="36.6" clip-path="url(#terminal-3378394567-line-0)">]&#160;[</text><text class="terminal-3378394567-r4" x="780.8" y="20" textLength="24.4" clip-path="url(#terminal-3378394567-line-0)">-m</text><text class="terminal-3378394567-r2" x="805.2" y="20" textLength="36.6" clip-path="url(#terminal-3378394567-line-0)">]&#160;[</text><text class="terminal-3378394567-r4" x="841.8" y="20" textLength="24.4" clip-path="url(#terminal-3378394567-line-0)">-n</text><text class="terminal-3378394567-r2" x="866.2" y="20" textLength="24.4" clip-path="url(#terminal-3378394567-line-0)">]&#160;</text><text class="terminal-3378394567-r4" x="890.6" y="20" textLength="24.4" clip-path="url(#terminal-3378394567-line-0)">-p</text><text class="terminal-3378394567-r5" x="927.2" y="20" textLength="48.8" clip-path="url(#terminal-3378394567-line-0)">ROOT</text><text class="terminal-3378394567-r4" x="988.2" y="20" textLength="24.4" clip-path="url(#terminal-3378394567-line-0)">-t</text><text class="terminal-3378394567-r5" x="1024.8" y="20" textLength="61" clip-path="url(#terminal-3378394567-line-0)">TITLE</text><text class="terminal-3378394567-r4" x="1098" y="20" textLength="24.4" clip-path="url(#terminal-3378394567-line-0)">-w</text><text class="terminal-3378394567-r5" x="1134.6" y="20" textLength="36.6" clip-path="url(#terminal-3378394567-line-0)">URL</text><text class="terminal-3378394567-r2" x="1464" y="20" textLength="12.2" clip-path="url(#terminal-3378394567-line-0)">
</text><text class="terminal-1308707172-r2" x="0" y="44.4" textLength="231.8" clip-path="url(#terminal-1308707172-line-1)">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;[</text><text class="terminal-1308707172-r4" x="231.8" y="44.4" textLength="195.2" clip-path="url(#terminal-1308707172-line-1)">--exclude-folder</text><text class="terminal-1308707172-r5" x="439.2" y="44.4" textLength="73.2" clip-path="url(#terminal-1308707172-line-1)">FOLDER</text><text class="terminal-1308707172-r2" x="512.4" y="44.4" textLength="36.6" clip-path="url(#terminal-1308707172-line-1)">]&#160;[</text><text class="terminal-1308707172-r4" x="549" y="44.4" textLength="244" clip-path="url(#terminal-1308707172-line-1)">--ignore-other-files</text><text class="terminal-1308707172-r2" x="793" y="44.4" textLength="36.6" clip-path="url(#terminal-1308707172-line-1)">]&#160;[</text><text class="terminal-1308707172-r4" x="829.6" y="44.4" textLength="280.6" clip-path="url(#terminal-1308707172-line-1)">--regenerate-thumbnails</text><text class="terminal-1308707172-r2" x="1110.2" y="44.4" textLength="36.6" clip-path="url(#terminal-1308707172-line-1)">]&#160;[</text><text class="terminal-1308707172-r4" x="1146.8" y="44.4" textLength="207.4" clip-path="url(#terminal-1308707172-line-1)">--reread-metadata</text><text class="terminal-1308707172-r2" x="1354.2" y="44.4" textLength="12.2" clip-path="url(#terminal-1308707172-line-1)">]</text><text class="terminal-1308707172-r2" x="1464" y="44.4" textLength="12.2" clip-path="url(#terminal-1308707172-line-1)"> </text><text class="terminal-3378394567-r2" x="0" y="44.4" textLength="231.8" clip-path="url(#terminal-3378394567-line-1)">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;[</text><text class="terminal-3378394567-r4" x="231.8" y="44.4" textLength="195.2" clip-path="url(#terminal-3378394567-line-1)">--exclude-folder</text><text class="terminal-3378394567-r5" x="439.2" y="44.4" textLength="73.2" clip-path="url(#terminal-3378394567-line-1)">FOLDER</text><text class="terminal-3378394567-r2" x="512.4" y="44.4" textLength="36.6" clip-path="url(#terminal-3378394567-line-1)">]&#160;[</text><text class="terminal-3378394567-r4" x="549" y="44.4" textLength="219.6" clip-path="url(#terminal-3378394567-line-1)">--folderthumbnails</text><text class="terminal-3378394567-r2" x="768.6" y="44.4" textLength="36.6" clip-path="url(#terminal-3378394567-line-1)">]&#160;[</text><text class="terminal-3378394567-r4" x="805.2" y="44.4" textLength="244" clip-path="url(#terminal-3378394567-line-1)">--ignore-other-files</text><text class="terminal-3378394567-r2" x="1049.2" y="44.4" textLength="36.6" clip-path="url(#terminal-3378394567-line-1)">]&#160;[</text><text class="terminal-3378394567-r4" x="1085.8" y="44.4" textLength="280.6" clip-path="url(#terminal-3378394567-line-1)">--regenerate-thumbnails</text><text class="terminal-3378394567-r2" x="1366.4" y="44.4" textLength="12.2" clip-path="url(#terminal-3378394567-line-1)">]</text><text class="terminal-3378394567-r2" x="1464" y="44.4" textLength="12.2" clip-path="url(#terminal-3378394567-line-1)">
</text><text class="terminal-1308707172-r2" x="0" y="68.8" textLength="231.8" clip-path="url(#terminal-1308707172-line-2)">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;[</text><text class="terminal-1308707172-r4" x="231.8" y="68.8" textLength="170.8" clip-path="url(#terminal-1308707172-line-2)">--reverse-sort</text><text class="terminal-1308707172-r2" x="402.6" y="68.8" textLength="36.6" clip-path="url(#terminal-1308707172-line-2)">]&#160;[</text><text class="terminal-1308707172-r4" x="439.2" y="68.8" textLength="146.4" clip-path="url(#terminal-1308707172-line-2)">--theme-path</text><text class="terminal-1308707172-r5" x="597.8" y="68.8" textLength="48.8" clip-path="url(#terminal-1308707172-line-2)">PATH</text><text class="terminal-1308707172-r2" x="646.6" y="68.8" textLength="36.6" clip-path="url(#terminal-1308707172-line-2)">]&#160;[</text><text class="terminal-1308707172-r4" x="683.2" y="68.8" textLength="231.8" clip-path="url(#terminal-1308707172-line-2)">--use-fancy-folders</text><text class="terminal-1308707172-r2" x="915" y="68.8" textLength="36.6" clip-path="url(#terminal-1308707172-line-2)">]&#160;[</text><text class="terminal-1308707172-r4" x="951.6" y="68.8" textLength="109.8" clip-path="url(#terminal-1308707172-line-2)">--version</text><text class="terminal-1308707172-r2" x="1061.4" y="68.8" textLength="12.2" clip-path="url(#terminal-1308707172-line-2)">]</text><text class="terminal-1308707172-r2" x="1464" y="68.8" textLength="12.2" clip-path="url(#terminal-1308707172-line-2)"> </text><text class="terminal-3378394567-r2" x="0" y="68.8" textLength="231.8" clip-path="url(#terminal-3378394567-line-2)">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;[</text><text class="terminal-3378394567-r4" x="231.8" y="68.8" textLength="207.4" clip-path="url(#terminal-3378394567-line-2)">--reread-metadata</text><text class="terminal-3378394567-r2" x="439.2" y="68.8" textLength="36.6" clip-path="url(#terminal-3378394567-line-2)">]&#160;[</text><text class="terminal-3378394567-r4" x="475.8" y="68.8" textLength="195.2" clip-path="url(#terminal-3378394567-line-2)">--reread-sidecar</text><text class="terminal-3378394567-r2" x="671" y="68.8" textLength="36.6" clip-path="url(#terminal-3378394567-line-2)">]&#160;[</text><text class="terminal-3378394567-r4" x="707.6" y="68.8" textLength="170.8" clip-path="url(#terminal-3378394567-line-2)">--reverse-sort</text><text class="terminal-3378394567-r2" x="878.4" y="68.8" textLength="36.6" clip-path="url(#terminal-3378394567-line-2)">]&#160;[</text><text class="terminal-3378394567-r4" x="915" y="68.8" textLength="146.4" clip-path="url(#terminal-3378394567-line-2)">--theme-path</text><text class="terminal-3378394567-r5" x="1073.6" y="68.8" textLength="48.8" clip-path="url(#terminal-3378394567-line-2)">PATH</text><text class="terminal-3378394567-r2" x="1122.4" y="68.8" textLength="36.6" clip-path="url(#terminal-3378394567-line-2)">]&#160;[</text><text class="terminal-3378394567-r4" x="1159" y="68.8" textLength="231.8" clip-path="url(#terminal-3378394567-line-2)">--use-fancy-folders</text><text class="terminal-3378394567-r2" x="1390.8" y="68.8" textLength="12.2" clip-path="url(#terminal-3378394567-line-2)">]</text><text class="terminal-3378394567-r2" x="1464" y="68.8" textLength="12.2" clip-path="url(#terminal-3378394567-line-2)">
</text><text class="terminal-1308707172-r2" x="1464" y="93.2" textLength="12.2" clip-path="url(#terminal-1308707172-line-3)"> </text><text class="terminal-3378394567-r2" x="0" y="93.2" textLength="231.8" clip-path="url(#terminal-3378394567-line-3)">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;[</text><text class="terminal-3378394567-r4" x="231.8" y="93.2" textLength="109.8" clip-path="url(#terminal-3378394567-line-3)">--version</text><text class="terminal-3378394567-r2" x="341.6" y="93.2" textLength="12.2" clip-path="url(#terminal-3378394567-line-3)">]</text><text class="terminal-3378394567-r2" x="1464" y="93.2" textLength="12.2" clip-path="url(#terminal-3378394567-line-3)">
</text><text class="terminal-1308707172-r2" x="0" y="117.6" textLength="671" clip-path="url(#terminal-1308707172-line-4)">Generate&#160;HTML&#160;files&#160;for&#160;a&#160;static&#160;image&#160;hosting&#160;website.</text><text class="terminal-1308707172-r2" x="1464" y="117.6" textLength="12.2" clip-path="url(#terminal-1308707172-line-4)"> </text><text class="terminal-3378394567-r2" x="1464" y="117.6" textLength="12.2" clip-path="url(#terminal-3378394567-line-4)">
</text><text class="terminal-1308707172-r2" x="1464" y="142" textLength="12.2" clip-path="url(#terminal-1308707172-line-5)"> </text><text class="terminal-3378394567-r2" x="0" y="142" textLength="658.8" clip-path="url(#terminal-3378394567-line-5)">generate&#160;HTML&#160;files&#160;for&#160;a&#160;static&#160;image&#160;hosting&#160;website</text><text class="terminal-3378394567-r2" x="1464" y="142" textLength="12.2" clip-path="url(#terminal-3378394567-line-5)">
</text><text class="terminal-1308707172-r1" x="0" y="166.4" textLength="97.6" clip-path="url(#terminal-1308707172-line-6)">Options:</text><text class="terminal-1308707172-r2" x="1464" y="166.4" textLength="12.2" clip-path="url(#terminal-1308707172-line-6)"> </text><text class="terminal-3378394567-r2" x="1464" y="166.4" textLength="12.2" clip-path="url(#terminal-3378394567-line-6)">
</text><text class="terminal-1308707172-r4" x="24.4" y="190.8" textLength="24.4" clip-path="url(#terminal-1308707172-line-7)">-h</text><text class="terminal-1308707172-r2" x="48.8" y="190.8" textLength="24.4" clip-path="url(#terminal-1308707172-line-7)">,&#160;</text><text class="terminal-1308707172-r4" x="73.2" y="190.8" textLength="73.2" clip-path="url(#terminal-1308707172-line-7)">--help</text><text class="terminal-1308707172-r2" x="292.8" y="190.8" textLength="378.2" clip-path="url(#terminal-1308707172-line-7)">show&#160;this&#160;help&#160;message&#160;and&#160;exit</text><text class="terminal-1308707172-r2" x="1464" y="190.8" textLength="12.2" clip-path="url(#terminal-1308707172-line-7)"> </text><text class="terminal-3378394567-r1" x="0" y="190.8" textLength="97.6" clip-path="url(#terminal-3378394567-line-7)">Options:</text><text class="terminal-3378394567-r2" x="1464" y="190.8" textLength="12.2" clip-path="url(#terminal-3378394567-line-7)">
</text><text class="terminal-1308707172-r4" x="24.4" y="215.2" textLength="24.4" clip-path="url(#terminal-1308707172-line-8)">-a</text><text class="terminal-1308707172-r2" x="48.8" y="215.2" textLength="24.4" clip-path="url(#terminal-1308707172-line-8)">,&#160;</text><text class="terminal-1308707172-r4" x="73.2" y="215.2" textLength="158.6" clip-path="url(#terminal-1308707172-line-8)">--author-name</text><text class="terminal-1308707172-r5" x="244" y="215.2" textLength="73.2" clip-path="url(#terminal-1308707172-line-8)">AUTHOR</text><text class="terminal-1308707172-r2" x="1464" y="215.2" textLength="12.2" clip-path="url(#terminal-1308707172-line-8)"> </text><text class="terminal-3378394567-r4" x="24.4" y="215.2" textLength="24.4" clip-path="url(#terminal-3378394567-line-8)">-h</text><text class="terminal-3378394567-r2" x="48.8" y="215.2" textLength="24.4" clip-path="url(#terminal-3378394567-line-8)">,&#160;</text><text class="terminal-3378394567-r4" x="73.2" y="215.2" textLength="73.2" clip-path="url(#terminal-3378394567-line-8)">--help</text><text class="terminal-3378394567-r2" x="292.8" y="215.2" textLength="378.2" clip-path="url(#terminal-3378394567-line-8)">show&#160;this&#160;help&#160;message&#160;and&#160;exit</text><text class="terminal-3378394567-r2" x="1464" y="215.2" textLength="12.2" clip-path="url(#terminal-3378394567-line-8)">
</text><text class="terminal-1308707172-r2" x="292.8" y="239.6" textLength="402.6" clip-path="url(#terminal-1308707172-line-9)">Name&#160;of&#160;the&#160;author&#160;of&#160;the&#160;images.</text><text class="terminal-1308707172-r2" x="1464" y="239.6" textLength="12.2" clip-path="url(#terminal-1308707172-line-9)"> </text><text class="terminal-3378394567-r4" x="24.4" y="239.6" textLength="24.4" clip-path="url(#terminal-3378394567-line-9)">-a</text><text class="terminal-3378394567-r2" x="48.8" y="239.6" textLength="24.4" clip-path="url(#terminal-3378394567-line-9)">,&#160;</text><text class="terminal-3378394567-r4" x="73.2" y="239.6" textLength="158.6" clip-path="url(#terminal-3378394567-line-9)">--author-name</text><text class="terminal-3378394567-r5" x="244" y="239.6" textLength="73.2" clip-path="url(#terminal-3378394567-line-9)">AUTHOR</text><text class="terminal-3378394567-r2" x="1464" y="239.6" textLength="12.2" clip-path="url(#terminal-3378394567-line-9)">
</text><text class="terminal-1308707172-r4" x="24.4" y="264" textLength="24.4" clip-path="url(#terminal-1308707172-line-10)">-e</text><text class="terminal-1308707172-r2" x="48.8" y="264" textLength="24.4" clip-path="url(#terminal-1308707172-line-10)">,&#160;</text><text class="terminal-1308707172-r4" x="73.2" y="264" textLength="207.4" clip-path="url(#terminal-1308707172-line-10)">--file-extensions</text><text class="terminal-1308707172-r5" x="292.8" y="264" textLength="109.8" clip-path="url(#terminal-1308707172-line-10)">EXTENSION</text><text class="terminal-1308707172-r2" x="1464" y="264" textLength="12.2" clip-path="url(#terminal-1308707172-line-10)"> </text><text class="terminal-3378394567-r2" x="292.8" y="264" textLength="390.4" clip-path="url(#terminal-3378394567-line-10)">name&#160;of&#160;the&#160;author&#160;of&#160;the&#160;images</text><text class="terminal-3378394567-r2" x="1464" y="264" textLength="12.2" clip-path="url(#terminal-3378394567-line-10)">
</text><text class="terminal-1308707172-r2" x="292.8" y="288.4" textLength="744.2" clip-path="url(#terminal-1308707172-line-11)">File&#160;extensions&#160;to&#160;include&#160;(can&#160;be&#160;specified&#160;multiple&#160;times).</text><text class="terminal-1308707172-r2" x="1464" y="288.4" textLength="12.2" clip-path="url(#terminal-1308707172-line-11)"> </text><text class="terminal-3378394567-r4" x="24.4" y="288.4" textLength="24.4" clip-path="url(#terminal-3378394567-line-11)">-e</text><text class="terminal-3378394567-r2" x="48.8" y="288.4" textLength="24.4" clip-path="url(#terminal-3378394567-line-11)">,&#160;</text><text class="terminal-3378394567-r4" x="73.2" y="288.4" textLength="207.4" clip-path="url(#terminal-3378394567-line-11)">--file-extensions</text><text class="terminal-3378394567-r5" x="292.8" y="288.4" textLength="109.8" clip-path="url(#terminal-3378394567-line-11)">EXTENSION</text><text class="terminal-3378394567-r2" x="1464" y="288.4" textLength="12.2" clip-path="url(#terminal-3378394567-line-11)">
</text><text class="terminal-1308707172-r4" x="24.4" y="312.8" textLength="24.4" clip-path="url(#terminal-1308707172-line-12)">-l</text><text class="terminal-1308707172-r2" x="48.8" y="312.8" textLength="24.4" clip-path="url(#terminal-1308707172-line-12)">,&#160;</text><text class="terminal-1308707172-r4" x="73.2" y="312.8" textLength="170.8" clip-path="url(#terminal-1308707172-line-12)">--license-type</text><text class="terminal-1308707172-r5" x="256.2" y="312.8" textLength="85.4" clip-path="url(#terminal-1308707172-line-12)">LICENSE</text><text class="terminal-1308707172-r2" x="1464" y="312.8" textLength="12.2" clip-path="url(#terminal-1308707172-line-12)"> </text><text class="terminal-3378394567-r2" x="292.8" y="312.8" textLength="732" clip-path="url(#terminal-3378394567-line-12)">file&#160;extensions&#160;to&#160;include&#160;(can&#160;be&#160;specified&#160;multiple&#160;times)</text><text class="terminal-3378394567-r2" x="1464" y="312.8" textLength="12.2" clip-path="url(#terminal-3378394567-line-12)">
</text><text class="terminal-1308707172-r2" x="292.8" y="337.2" textLength="488" clip-path="url(#terminal-1308707172-line-13)">Specify&#160;the&#160;license&#160;type&#160;for&#160;the&#160;images.</text><text class="terminal-1308707172-r2" x="1464" y="337.2" textLength="12.2" clip-path="url(#terminal-1308707172-line-13)"> </text><text class="terminal-3378394567-r4" x="24.4" y="337.2" textLength="24.4" clip-path="url(#terminal-3378394567-line-13)">-l</text><text class="terminal-3378394567-r2" x="48.8" y="337.2" textLength="24.4" clip-path="url(#terminal-3378394567-line-13)">,&#160;</text><text class="terminal-3378394567-r4" x="73.2" y="337.2" textLength="170.8" clip-path="url(#terminal-3378394567-line-13)">--license-type</text><text class="terminal-3378394567-r5" x="256.2" y="337.2" textLength="85.4" clip-path="url(#terminal-3378394567-line-13)">LICENSE</text><text class="terminal-3378394567-r2" x="1464" y="337.2" textLength="12.2" clip-path="url(#terminal-3378394567-line-13)">
</text><text class="terminal-1308707172-r4" x="24.4" y="361.6" textLength="24.4" clip-path="url(#terminal-1308707172-line-14)">-m</text><text class="terminal-1308707172-r2" x="48.8" y="361.6" textLength="24.4" clip-path="url(#terminal-1308707172-line-14)">,&#160;</text><text class="terminal-1308707172-r4" x="73.2" y="361.6" textLength="170.8" clip-path="url(#terminal-1308707172-line-14)">--web-manifest</text><text class="terminal-1308707172-r2" x="292.8" y="361.6" textLength="353.8" clip-path="url(#terminal-1308707172-line-14)">Generate&#160;a&#160;web&#160;manifest&#160;file.</text><text class="terminal-1308707172-r2" x="1464" y="361.6" textLength="12.2" clip-path="url(#terminal-1308707172-line-14)"> </text><text class="terminal-3378394567-r2" x="292.8" y="361.6" textLength="475.8" clip-path="url(#terminal-3378394567-line-14)">specify&#160;the&#160;license&#160;type&#160;for&#160;the&#160;images</text><text class="terminal-3378394567-r2" x="1464" y="361.6" textLength="12.2" clip-path="url(#terminal-3378394567-line-14)">
</text><text class="terminal-1308707172-r4" x="24.4" y="386" textLength="24.4" clip-path="url(#terminal-1308707172-line-15)">-n</text><text class="terminal-1308707172-r2" x="48.8" y="386" textLength="24.4" clip-path="url(#terminal-1308707172-line-15)">,&#160;</text><text class="terminal-1308707172-r4" x="73.2" y="386" textLength="268.4" clip-path="url(#terminal-1308707172-line-15)">--non-interactive-mode</text><text class="terminal-1308707172-r2" x="1464" y="386" textLength="12.2" clip-path="url(#terminal-1308707172-line-15)"> </text><text class="terminal-3378394567-r4" x="24.4" y="386" textLength="24.4" clip-path="url(#terminal-3378394567-line-15)">-m</text><text class="terminal-3378394567-r2" x="48.8" y="386" textLength="24.4" clip-path="url(#terminal-3378394567-line-15)">,&#160;</text><text class="terminal-3378394567-r4" x="73.2" y="386" textLength="170.8" clip-path="url(#terminal-3378394567-line-15)">--web-manifest</text><text class="terminal-3378394567-r2" x="292.8" y="386" textLength="341.6" clip-path="url(#terminal-3378394567-line-15)">generate&#160;a&#160;web&#160;manifest&#160;file</text><text class="terminal-3378394567-r2" x="1464" y="386" textLength="12.2" clip-path="url(#terminal-3378394567-line-15)">
</text><text class="terminal-1308707172-r2" x="292.8" y="410.4" textLength="646.6" clip-path="url(#terminal-1308707172-line-16)">Run&#160;in&#160;non-interactive&#160;mode,&#160;disabling&#160;progress&#160;bars.</text><text class="terminal-1308707172-r2" x="1464" y="410.4" textLength="12.2" clip-path="url(#terminal-1308707172-line-16)"> </text><text class="terminal-3378394567-r4" x="24.4" y="410.4" textLength="24.4" clip-path="url(#terminal-3378394567-line-16)">-n</text><text class="terminal-3378394567-r2" x="48.8" y="410.4" textLength="24.4" clip-path="url(#terminal-3378394567-line-16)">,&#160;</text><text class="terminal-3378394567-r4" x="73.2" y="410.4" textLength="268.4" clip-path="url(#terminal-3378394567-line-16)">--non-interactive-mode</text><text class="terminal-3378394567-r2" x="1464" y="410.4" textLength="12.2" clip-path="url(#terminal-3378394567-line-16)">
</text><text class="terminal-1308707172-r4" x="24.4" y="434.8" textLength="24.4" clip-path="url(#terminal-1308707172-line-17)">-p</text><text class="terminal-1308707172-r2" x="48.8" y="434.8" textLength="24.4" clip-path="url(#terminal-1308707172-line-17)">,&#160;</text><text class="terminal-1308707172-r4" x="73.2" y="434.8" textLength="195.2" clip-path="url(#terminal-1308707172-line-17)">--root-directory</text><text class="terminal-1308707172-r5" x="280.6" y="434.8" textLength="48.8" clip-path="url(#terminal-1308707172-line-17)">ROOT</text><text class="terminal-1308707172-r2" x="1464" y="434.8" textLength="12.2" clip-path="url(#terminal-1308707172-line-17)"> </text><text class="terminal-3378394567-r2" x="292.8" y="434.8" textLength="634.4" clip-path="url(#terminal-3378394567-line-17)">run&#160;in&#160;non-interactive&#160;mode,&#160;disabling&#160;progress&#160;bars</text><text class="terminal-3378394567-r2" x="1464" y="434.8" textLength="12.2" clip-path="url(#terminal-3378394567-line-17)">
</text><text class="terminal-1308707172-r2" x="292.8" y="459.2" textLength="451.4" clip-path="url(#terminal-1308707172-line-18)">Root&#160;directory&#160;containing&#160;the&#160;images.</text><text class="terminal-1308707172-r2" x="1464" y="459.2" textLength="12.2" clip-path="url(#terminal-1308707172-line-18)"> </text><text class="terminal-3378394567-r4" x="24.4" y="459.2" textLength="24.4" clip-path="url(#terminal-3378394567-line-18)">-p</text><text class="terminal-3378394567-r2" x="48.8" y="459.2" textLength="24.4" clip-path="url(#terminal-3378394567-line-18)">,&#160;</text><text class="terminal-3378394567-r4" x="73.2" y="459.2" textLength="195.2" clip-path="url(#terminal-3378394567-line-18)">--root-directory</text><text class="terminal-3378394567-r5" x="280.6" y="459.2" textLength="48.8" clip-path="url(#terminal-3378394567-line-18)">ROOT</text><text class="terminal-3378394567-r2" x="1464" y="459.2" textLength="12.2" clip-path="url(#terminal-3378394567-line-18)">
</text><text class="terminal-1308707172-r4" x="24.4" y="483.6" textLength="24.4" clip-path="url(#terminal-1308707172-line-19)">-t</text><text class="terminal-1308707172-r2" x="48.8" y="483.6" textLength="24.4" clip-path="url(#terminal-1308707172-line-19)">,&#160;</text><text class="terminal-1308707172-r4" x="73.2" y="483.6" textLength="146.4" clip-path="url(#terminal-1308707172-line-19)">--site-title</text><text class="terminal-1308707172-r5" x="231.8" y="483.6" textLength="61" clip-path="url(#terminal-1308707172-line-19)">TITLE</text><text class="terminal-1308707172-r2" x="1464" y="483.6" textLength="12.2" clip-path="url(#terminal-1308707172-line-19)"> </text><text class="terminal-3378394567-r2" x="292.8" y="483.6" textLength="439.2" clip-path="url(#terminal-3378394567-line-19)">root&#160;directory&#160;containing&#160;the&#160;images</text><text class="terminal-3378394567-r2" x="1464" y="483.6" textLength="12.2" clip-path="url(#terminal-3378394567-line-19)">
</text><text class="terminal-1308707172-r2" x="292.8" y="508" textLength="390.4" clip-path="url(#terminal-1308707172-line-20)">Title&#160;of&#160;the&#160;image&#160;hosting&#160;site.</text><text class="terminal-1308707172-r2" x="1464" y="508" textLength="12.2" clip-path="url(#terminal-1308707172-line-20)"> </text><text class="terminal-3378394567-r4" x="24.4" y="508" textLength="24.4" clip-path="url(#terminal-3378394567-line-20)">-t</text><text class="terminal-3378394567-r2" x="48.8" y="508" textLength="24.4" clip-path="url(#terminal-3378394567-line-20)">,&#160;</text><text class="terminal-3378394567-r4" x="73.2" y="508" textLength="146.4" clip-path="url(#terminal-3378394567-line-20)">--site-title</text><text class="terminal-3378394567-r5" x="231.8" y="508" textLength="61" clip-path="url(#terminal-3378394567-line-20)">TITLE</text><text class="terminal-3378394567-r2" x="1464" y="508" textLength="12.2" clip-path="url(#terminal-3378394567-line-20)">
</text><text class="terminal-1308707172-r4" x="24.4" y="532.4" textLength="24.4" clip-path="url(#terminal-1308707172-line-21)">-w</text><text class="terminal-1308707172-r2" x="48.8" y="532.4" textLength="24.4" clip-path="url(#terminal-1308707172-line-21)">,&#160;</text><text class="terminal-1308707172-r4" x="73.2" y="532.4" textLength="170.8" clip-path="url(#terminal-1308707172-line-21)">--web-root-url</text><text class="terminal-1308707172-r5" x="256.2" y="532.4" textLength="36.6" clip-path="url(#terminal-1308707172-line-21)">URL</text><text class="terminal-1308707172-r2" x="1464" y="532.4" textLength="12.2" clip-path="url(#terminal-1308707172-line-21)"> </text><text class="terminal-3378394567-r2" x="292.8" y="532.4" textLength="378.2" clip-path="url(#terminal-3378394567-line-21)">title&#160;of&#160;the&#160;image&#160;hosting&#160;site</text><text class="terminal-3378394567-r2" x="1464" y="532.4" textLength="12.2" clip-path="url(#terminal-3378394567-line-21)">
</text><text class="terminal-1308707172-r2" x="292.8" y="556.8" textLength="634.4" clip-path="url(#terminal-1308707172-line-22)">Base&#160;URL&#160;of&#160;the&#160;web&#160;root&#160;for&#160;the&#160;image&#160;hosting&#160;site.</text><text class="terminal-1308707172-r2" x="1464" y="556.8" textLength="12.2" clip-path="url(#terminal-1308707172-line-22)"> </text><text class="terminal-3378394567-r4" x="24.4" y="556.8" textLength="24.4" clip-path="url(#terminal-3378394567-line-22)">-w</text><text class="terminal-3378394567-r2" x="48.8" y="556.8" textLength="24.4" clip-path="url(#terminal-3378394567-line-22)">,&#160;</text><text class="terminal-3378394567-r4" x="73.2" y="556.8" textLength="170.8" clip-path="url(#terminal-3378394567-line-22)">--web-root-url</text><text class="terminal-3378394567-r5" x="256.2" y="556.8" textLength="36.6" clip-path="url(#terminal-3378394567-line-22)">URL</text><text class="terminal-3378394567-r2" x="1464" y="556.8" textLength="12.2" clip-path="url(#terminal-3378394567-line-22)">
</text><text class="terminal-1308707172-r4" x="24.4" y="581.2" textLength="195.2" clip-path="url(#terminal-1308707172-line-23)">--exclude-folder</text><text class="terminal-1308707172-r5" x="231.8" y="581.2" textLength="73.2" clip-path="url(#terminal-1308707172-line-23)">FOLDER</text><text class="terminal-1308707172-r2" x="1464" y="581.2" textLength="12.2" clip-path="url(#terminal-1308707172-line-23)"> </text><text class="terminal-3378394567-r2" x="292.8" y="581.2" textLength="622.2" clip-path="url(#terminal-3378394567-line-23)">base&#160;URL&#160;of&#160;the&#160;web&#160;root&#160;for&#160;the&#160;image&#160;hosting&#160;site</text><text class="terminal-3378394567-r2" x="1464" y="581.2" textLength="12.2" clip-path="url(#terminal-3378394567-line-23)">
</text><text class="terminal-1308707172-r2" x="292.8" y="605.6" textLength="1049.2" clip-path="url(#terminal-1308707172-line-24)">Folders&#160;to&#160;exclude&#160;from&#160;processing,&#160;globs&#160;supported&#160;(can&#160;be&#160;specified&#160;multiple&#160;times).</text><text class="terminal-1308707172-r2" x="1464" y="605.6" textLength="12.2" clip-path="url(#terminal-1308707172-line-24)"> </text><text class="terminal-3378394567-r4" x="24.4" y="605.6" textLength="195.2" clip-path="url(#terminal-3378394567-line-24)">--exclude-folder</text><text class="terminal-3378394567-r5" x="231.8" y="605.6" textLength="73.2" clip-path="url(#terminal-3378394567-line-24)">FOLDER</text><text class="terminal-3378394567-r2" x="1464" y="605.6" textLength="12.2" clip-path="url(#terminal-3378394567-line-24)">
</text><text class="terminal-1308707172-r4" x="24.4" y="630" textLength="244" clip-path="url(#terminal-1308707172-line-25)">--ignore-other-files</text><text class="terminal-1308707172-r2" x="292.8" y="630" textLength="683.2" clip-path="url(#terminal-1308707172-line-25)">Ignore&#160;files&#160;that&#160;do&#160;not&#160;match&#160;the&#160;specified&#160;extensions.</text><text class="terminal-1308707172-r2" x="1464" y="630" textLength="12.2" clip-path="url(#terminal-1308707172-line-25)"> </text><text class="terminal-3378394567-r2" x="292.8" y="630" textLength="1037" clip-path="url(#terminal-3378394567-line-25)">folders&#160;to&#160;exclude&#160;from&#160;processing,&#160;globs&#160;supported&#160;(can&#160;be&#160;specified&#160;multiple&#160;times)</text><text class="terminal-3378394567-r2" x="1464" y="630" textLength="12.2" clip-path="url(#terminal-3378394567-line-25)">
</text><text class="terminal-1308707172-r4" x="24.4" y="654.4" textLength="280.6" clip-path="url(#terminal-1308707172-line-26)">--regenerate-thumbnails</text><text class="terminal-1308707172-r2" x="1464" y="654.4" textLength="12.2" clip-path="url(#terminal-1308707172-line-26)"> </text><text class="terminal-3378394567-r4" x="24.4" y="654.4" textLength="219.6" clip-path="url(#terminal-3378394567-line-26)">--folderthumbnails</text><text class="terminal-3378394567-r2" x="292.8" y="654.4" textLength="817.4" clip-path="url(#terminal-3378394567-line-26)">generate&#160;subfolder&#160;thumbnails&#160;(first&#160;image&#160;in&#160;folder&#160;will&#160;be&#160;shown)</text><text class="terminal-3378394567-r2" x="1464" y="654.4" textLength="12.2" clip-path="url(#terminal-3378394567-line-26)">
</text><text class="terminal-1308707172-r2" x="292.8" y="678.8" textLength="597.8" clip-path="url(#terminal-1308707172-line-27)">Regenerate&#160;thumbnails&#160;even&#160;if&#160;they&#160;already&#160;exist.</text><text class="terminal-1308707172-r2" x="1464" y="678.8" textLength="12.2" clip-path="url(#terminal-1308707172-line-27)"> </text><text class="terminal-3378394567-r4" x="24.4" y="678.8" textLength="244" clip-path="url(#terminal-3378394567-line-27)">--ignore-other-files</text><text class="terminal-3378394567-r2" x="292.8" y="678.8" textLength="671" clip-path="url(#terminal-3378394567-line-27)">ignore&#160;files&#160;that&#160;do&#160;not&#160;match&#160;the&#160;specified&#160;extensions</text><text class="terminal-3378394567-r2" x="1464" y="678.8" textLength="12.2" clip-path="url(#terminal-3378394567-line-27)">
</text><text class="terminal-1308707172-r4" x="24.4" y="703.2" textLength="207.4" clip-path="url(#terminal-1308707172-line-28)">--reread-metadata</text><text class="terminal-1308707172-r2" x="292.8" y="703.2" textLength="256.2" clip-path="url(#terminal-1308707172-line-28)">Reread&#160;image&#160;metadata</text><text class="terminal-1308707172-r2" x="1464" y="703.2" textLength="12.2" clip-path="url(#terminal-1308707172-line-28)"> </text><text class="terminal-3378394567-r4" x="24.4" y="703.2" textLength="280.6" clip-path="url(#terminal-3378394567-line-28)">--regenerate-thumbnails</text><text class="terminal-3378394567-r2" x="1464" y="703.2" textLength="12.2" clip-path="url(#terminal-3378394567-line-28)">
</text><text class="terminal-1308707172-r4" x="24.4" y="727.6" textLength="170.8" clip-path="url(#terminal-1308707172-line-29)">--reverse-sort</text><text class="terminal-1308707172-r2" x="292.8" y="727.6" textLength="353.8" clip-path="url(#terminal-1308707172-line-29)">Sort&#160;images&#160;in&#160;reverse&#160;order.</text><text class="terminal-1308707172-r2" x="1464" y="727.6" textLength="12.2" clip-path="url(#terminal-1308707172-line-29)"> </text><text class="terminal-3378394567-r2" x="292.8" y="727.6" textLength="585.6" clip-path="url(#terminal-3378394567-line-29)">regenerate&#160;thumbnails&#160;even&#160;if&#160;they&#160;already&#160;exist</text><text class="terminal-3378394567-r2" x="1464" y="727.6" textLength="12.2" clip-path="url(#terminal-3378394567-line-29)">
</text><text class="terminal-1308707172-r4" x="24.4" y="752" textLength="146.4" clip-path="url(#terminal-1308707172-line-30)">--theme-path</text><text class="terminal-1308707172-r5" x="183" y="752" textLength="48.8" clip-path="url(#terminal-1308707172-line-30)">PATH</text><text class="terminal-1308707172-r2" x="292.8" y="752" textLength="329.4" clip-path="url(#terminal-1308707172-line-30)">Path&#160;to&#160;the&#160;CSS&#160;theme&#160;file.</text><text class="terminal-1308707172-r2" x="1464" y="752" textLength="12.2" clip-path="url(#terminal-1308707172-line-30)"> </text><text class="terminal-3378394567-r4" x="24.4" y="752" textLength="207.4" clip-path="url(#terminal-3378394567-line-30)">--reread-metadata</text><text class="terminal-3378394567-r2" x="292.8" y="752" textLength="256.2" clip-path="url(#terminal-3378394567-line-30)">reread&#160;image&#160;metadata</text><text class="terminal-3378394567-r2" x="1464" y="752" textLength="12.2" clip-path="url(#terminal-3378394567-line-30)">
</text><text class="terminal-1308707172-r4" x="24.4" y="776.4" textLength="231.8" clip-path="url(#terminal-1308707172-line-31)">--use-fancy-folders</text><text class="terminal-1308707172-r2" x="292.8" y="776.4" textLength="890.6" clip-path="url(#terminal-1308707172-line-31)">Enable&#160;fancy&#160;folder&#160;view&#160;instead&#160;of&#160;the&#160;default&#160;Apache&#160;directory&#160;listing.</text><text class="terminal-1308707172-r2" x="1464" y="776.4" textLength="12.2" clip-path="url(#terminal-1308707172-line-31)"> </text><text class="terminal-3378394567-r4" x="24.4" y="776.4" textLength="195.2" clip-path="url(#terminal-3378394567-line-31)">--reread-sidecar</text><text class="terminal-3378394567-r2" x="292.8" y="776.4" textLength="244" clip-path="url(#terminal-3378394567-line-31)">reread&#160;sidecar&#160;files</text><text class="terminal-3378394567-r2" x="1464" y="776.4" textLength="12.2" clip-path="url(#terminal-3378394567-line-31)">
</text><text class="terminal-1308707172-r4" x="24.4" y="800.8" textLength="109.8" clip-path="url(#terminal-1308707172-line-32)">--version</text><text class="terminal-1308707172-r2" x="292.8" y="800.8" textLength="463.6" clip-path="url(#terminal-1308707172-line-32)">show&#160;program&#x27;s&#160;version&#160;number&#160;and&#160;exit</text><text class="terminal-1308707172-r2" x="1464" y="800.8" textLength="12.2" clip-path="url(#terminal-1308707172-line-32)"> </text><text class="terminal-3378394567-r4" x="24.4" y="800.8" textLength="170.8" clip-path="url(#terminal-3378394567-line-32)">--reverse-sort</text><text class="terminal-3378394567-r2" x="292.8" y="800.8" textLength="341.6" clip-path="url(#terminal-3378394567-line-32)">sort&#160;images&#160;in&#160;reverse&#160;order</text><text class="terminal-3378394567-r2" x="1464" y="800.8" textLength="12.2" clip-path="url(#terminal-3378394567-line-32)">
</text><text class="terminal-3378394567-r4" x="24.4" y="825.2" textLength="146.4" clip-path="url(#terminal-3378394567-line-33)">--theme-path</text><text class="terminal-3378394567-r5" x="183" y="825.2" textLength="48.8" clip-path="url(#terminal-3378394567-line-33)">PATH</text><text class="terminal-3378394567-r2" x="292.8" y="825.2" textLength="317.2" clip-path="url(#terminal-3378394567-line-33)">path&#160;to&#160;the&#160;CSS&#160;theme&#160;file</text><text class="terminal-3378394567-r2" x="1464" y="825.2" textLength="12.2" clip-path="url(#terminal-3378394567-line-33)">
</text><text class="terminal-3378394567-r4" x="24.4" y="849.6" textLength="231.8" clip-path="url(#terminal-3378394567-line-34)">--use-fancy-folders</text><text class="terminal-3378394567-r2" x="292.8" y="849.6" textLength="878.4" clip-path="url(#terminal-3378394567-line-34)">enable&#160;fancy&#160;folder&#160;view&#160;instead&#160;of&#160;the&#160;default&#160;Apache&#160;directory&#160;listing</text><text class="terminal-3378394567-r2" x="1464" y="849.6" textLength="12.2" clip-path="url(#terminal-3378394567-line-34)">
</text><text class="terminal-3378394567-r4" x="24.4" y="874" textLength="109.8" clip-path="url(#terminal-3378394567-line-35)">--version</text><text class="terminal-3378394567-r2" x="292.8" y="874" textLength="463.6" clip-path="url(#terminal-3378394567-line-35)">show&#160;program&#x27;s&#160;version&#160;number&#160;and&#160;exit</text><text class="terminal-3378394567-r2" x="1464" y="874" textLength="12.2" clip-path="url(#terminal-3378394567-line-35)">
</text> </text>
</g> </g>
</g> </g>

Before

Width:  |  Height:  |  Size: 25 KiB

After

Width:  |  Height:  |  Size: 28 KiB

View File

@@ -67,6 +67,7 @@ class Args:
non_interactive_mode: bool non_interactive_mode: bool
regenerate_thumbnails: bool regenerate_thumbnails: bool
reread_metadata: bool reread_metadata: bool
reread_sidecar: bool
reverse_sort: bool reverse_sort: bool
root_directory: str root_directory: str
site_title: str site_title: str
@@ -87,6 +88,7 @@ class Args:
result["non_interactive_mode"] = self.non_interactive_mode result["non_interactive_mode"] = self.non_interactive_mode
result["regenerate_thumbnails"] = self.regenerate_thumbnails result["regenerate_thumbnails"] = self.regenerate_thumbnails
result["reread_metadata"] = self.reread_metadata result["reread_metadata"] = self.reread_metadata
result["reread_sidecar"] = self.reread_sidecar
result["reverse_sort"] = self.reverse_sort result["reverse_sort"] = self.reverse_sort
result["root_directory"] = self.root_directory result["root_directory"] = self.root_directory
result["site_title"] = self.site_title result["site_title"] = self.site_title
@@ -112,27 +114,28 @@ def parse_arguments(version: str) -> Args:
""" """
# fmt: off # fmt: off
if RICH: if RICH:
parser = argparse.ArgumentParser(description="Generate HTML files for a static image hosting website.", formatter_class=RichHelpFormatter) parser = argparse.ArgumentParser(description="generate HTML files for a static image hosting website", formatter_class=RichHelpFormatter)
else: else:
parser = argparse.ArgumentParser(description="Generate HTML files for a static image hosting website.") parser = argparse.ArgumentParser(description="generate HTML files for a static image hosting website")
parser.add_argument("-a", "--author-name", help="Name of the author of the images.", default=DEFAULT_AUTHOR, type=str, dest="author_name", metavar="AUTHOR") parser.add_argument("-a", "--author-name", help="name of the author of the images", default=DEFAULT_AUTHOR, type=str, dest="author_name", metavar="AUTHOR")
parser.add_argument("-e", "--file-extensions", help="File extensions to include (can be specified multiple times).", action="append", dest="file_extensions", metavar="EXTENSION") parser.add_argument("-e", "--file-extensions", help="file extensions to include (can be specified multiple times)", action="append", dest="file_extensions", metavar="EXTENSION")
parser.add_argument("-l", "--license-type", help="Specify the license type for the images.", choices=["cc-zero", "cc-by", "cc-by-sa", "cc-by-nd", "cc-by-nc", "cc-by-nc-sa", "cc-by-nc-nd"], default=None, dest="license_type", metavar="LICENSE") parser.add_argument("-l", "--license-type", help="specify the license type for the images", choices=["cc-zero", "cc-by", "cc-by-sa", "cc-by-nd", "cc-by-nc", "cc-by-nc-sa", "cc-by-nc-nd"], default=None, dest="license_type", metavar="LICENSE")
parser.add_argument("-m", "--web-manifest", help="Generate a web manifest file.", action="store_true", default=False, dest="generate_webmanifest") parser.add_argument("-m", "--web-manifest", help="generate a web manifest file", action="store_true", default=False, dest="generate_webmanifest")
parser.add_argument("-n", "--non-interactive-mode", help="Run in non-interactive mode, disabling progress bars.", action="store_true", default=False, dest="non_interactive_mode") parser.add_argument("-n", "--non-interactive-mode", help="run in non-interactive mode, disabling progress bars", action="store_true", default=False, dest="non_interactive_mode")
parser.add_argument("-p", "--root-directory", help="Root directory containing the images.", required=True, type=str, dest="root_directory", metavar="ROOT") parser.add_argument("-p", "--root-directory", help="root directory containing the images", required=True, type=str, dest="root_directory", metavar="ROOT")
parser.add_argument("-t", "--site-title", help="Title of the image hosting site.", required=True, type=str, dest="site_title", metavar="TITLE") parser.add_argument("-t", "--site-title", help="title of the image hosting site", required=True, type=str, dest="site_title", metavar="TITLE")
parser.add_argument("-w", "--web-root-url", help="Base URL of the web root for the image hosting site.", required=True, type=str, dest="web_root_url", metavar="URL") parser.add_argument("-w", "--web-root-url", help="base URL of the web root for the image hosting site", required=True, type=str, dest="web_root_url", metavar="URL")
parser.add_argument("--exclude-folder", help="Folders to exclude from processing, globs supported (can be specified multiple times).", action="append", dest="exclude_folders", metavar="FOLDER") parser.add_argument("--exclude-folder", help="folders to exclude from processing, globs supported (can be specified multiple times)", action="append", dest="exclude_folders", metavar="FOLDER")
parser.add_argument("--folderthumbnails", help="Generate subfolder thumbnails (first image in folder will be shown)", action="store_true", default=False, dest="folder_thumbs") parser.add_argument("--folderthumbnails", help="generate subfolder thumbnails (first image in folder will be shown)", action="store_true", default=False, dest="folder_thumbs")
if RICH: if RICH:
parser.add_argument("--generate-help-preview", action=HelpPreviewAction, path="help.svg", ) parser.add_argument("--generate-help-preview", action=HelpPreviewAction, path="help.svg", )
parser.add_argument("--ignore-other-files", help="Ignore files that do not match the specified extensions.", action="store_true", default=False, dest="ignore_other_files") parser.add_argument("--ignore-other-files", help="ignore files that do not match the specified extensions", action="store_true", default=False, dest="ignore_other_files")
parser.add_argument("--regenerate-thumbnails", help="Regenerate thumbnails even if they already exist.", action="store_true", default=False, dest="regenerate_thumbnails") parser.add_argument("--regenerate-thumbnails", help="regenerate thumbnails even if they already exist", action="store_true", default=False, dest="regenerate_thumbnails")
parser.add_argument("--reread-metadata", help="Reread image metadata", action="store_true", default=False, dest="reread_metadata") parser.add_argument("--reread-metadata", help="reread image metadata", action="store_true", default=False, dest="reread_metadata")
parser.add_argument("--reverse-sort", help="Sort images in reverse order.", action="store_true", default=False, dest="reverse_sort") parser.add_argument("--reread-sidecar", help="reread sidecar files", action="store_true", default=False, dest="reread_sidecar")
parser.add_argument("--theme-path", help="Path to the CSS theme file.", default=DEFAULT_THEME_PATH, type=str, dest="theme_path", metavar="PATH") parser.add_argument("--reverse-sort", help="sort images in reverse order", action="store_true", default=False, dest="reverse_sort")
parser.add_argument("--use-fancy-folders", help="Enable fancy folder view instead of the default Apache directory listing.", action="store_true", default=False, dest="use_fancy_folders") parser.add_argument("--theme-path", help="path to the CSS theme file", default=DEFAULT_THEME_PATH, type=str, dest="theme_path", metavar="PATH")
parser.add_argument("--use-fancy-folders", help="enable fancy folder view instead of the default Apache directory listing", action="store_true", default=False, dest="use_fancy_folders")
parser.add_argument("--version", action="version", version=f"%(prog)s {version}") parser.add_argument("--version", action="version", version=f"%(prog)s {version}")
parsed_args = parser.parse_args() parsed_args = parser.parse_args()
# fmt: on # fmt: on
@@ -147,6 +150,7 @@ def parse_arguments(version: str) -> Args:
non_interactive_mode=parsed_args.non_interactive_mode, non_interactive_mode=parsed_args.non_interactive_mode,
regenerate_thumbnails=parsed_args.regenerate_thumbnails, regenerate_thumbnails=parsed_args.regenerate_thumbnails,
reread_metadata=parsed_args.reread_metadata, reread_metadata=parsed_args.reread_metadata,
reread_sidecar=parsed_args.reread_sidecar,
reverse_sort=parsed_args.reverse_sort, reverse_sort=parsed_args.reverse_sort,
root_directory=parsed_args.root_directory, root_directory=parsed_args.root_directory,
site_title=parsed_args.site_title, site_title=parsed_args.site_title,

View File

@@ -5,6 +5,7 @@ import fnmatch
import json import json
from typing import Any from typing import Any
from datetime import datetime from datetime import datetime
from collections import defaultdict
from tqdm.auto import tqdm from tqdm.auto import tqdm
from PIL import Image, ExifTags, TiffImagePlugin, UnidentifiedImageError from PIL import Image, ExifTags, TiffImagePlugin, UnidentifiedImageError
@@ -97,8 +98,32 @@ def initialize_metadata(folder: str) -> dict[str, dict[str, int]]:
# remove old sizelist if it exists # remove old sizelist if it exists
sizelist_path = os.path.join(folder, ".sizelist.json") sizelist_path = os.path.join(folder, ".sizelist.json")
if os.path.exists(sizelist_path): if os.path.exists(sizelist_path):
with open(sizelist_path, "r") as sizelist:
metadata = json.loads(sizelist.read())
logger.warning("found old .sizelist.json, removing it...", extra={"path": sizelist_path}) logger.warning("found old .sizelist.json, removing it...", extra={"path": sizelist_path})
os.remove(sizelist_path) os.remove(sizelist_path)
# convert from old metadata format
if "images" not in metadata and "subfolders" not in metadata:
images = metadata.copy()
metadata = {}
metadata["images"] = images
elif "images" not in metadata:
metadata["images"] = {}
for k, v in metadata["images"].items():
if "width" in v:
metadata["images"][k]["w"] = v["width"]
del metadata["images"][k]["width"]
if "height" in v:
metadata["images"][k]["h"] = v["height"]
del metadata["images"][k]["height"]
if "tags" not in v:
metadata["images"][k]["tags"] = []
if "exifdata" not in v:
metadata["images"][k]["exifdata"] = None
if "xmp" not in v:
metadata["images"][k]["xmp"] = None
return metadata return metadata
@@ -143,7 +168,7 @@ def get_image_info(item: str, folder: str) -> dict[str, Any]:
except UnidentifiedImageError: except UnidentifiedImageError:
logger.error("cannot identify image file", extra={"file": file}) logger.error("cannot identify image file", extra={"file": file})
print(f"cannot identify image file: {file}") print(f"cannot identify image file: {file}")
return {"width": None, "height": None, "tags": None, "exifdata": None, "xmp": None} return {"w": None, "h": None, "tags": None, "exifdata": None, "xmp": None}
if exif: if exif:
logger.info("extracting EXIF data", extra={"file": file}) logger.info("extracting EXIF data", extra={"file": file})
ifd = exif.get_ifd(ExifTags.IFD.Exif) ifd = exif.get_ifd(ExifTags.IFD.Exif)
@@ -189,23 +214,70 @@ def get_image_info(item: str, folder: str) -> dict[str, Any]:
tags = xmpdata["xmpmeta"]["RDF"]["Description"]["subject"]["Bag"]["li"] tags = xmpdata["xmpmeta"]["RDF"]["Description"]["subject"]["Bag"]["li"]
if isinstance(tags, str): if isinstance(tags, str):
tags = [tags] tags = [tags]
xmp = xmpdata
except TypeError: except TypeError:
... pass
except KeyError: except KeyError:
... pass
try: try:
tags = xmpdata["xapmeta"]["RDF"]["Description"]["subject"]["Bag"]["li"] tags = xmpdata["xapmeta"]["RDF"]["Description"]["subject"]["Bag"]["li"]
if isinstance(tags, str): if isinstance(tags, str):
tags = [tags] tags = [tags]
xmp = xmpdata
except TypeError: except TypeError:
... pass
except KeyError: 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
sidecarfile = os.path.join(folder, item + ".xmp")
if os.path.exists(sidecarfile):
logger.info("xmp sidecar file found", extra={"file": sidecarfile})
try:
tags = get_tags(sidecarfile)
except Exception as e:
logger.error(e)
if None in tags: if None in tags:
tags.remove(None) tags.remove(None)
return {"width": width, "height": height, "tags": tags, "exifdata": exifdata, "xmp": xmp} return {"w": width, "h": height, "tags": tags, "exifdata": exifdata, "xmp": xmp}
def nested_dict():
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):
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]: def get_tags(sidecarfile: str) -> list[str]:
@@ -228,17 +300,33 @@ def get_tags(sidecarfile: str) -> list[str]:
if isinstance(tags, str): if isinstance(tags, str):
tags = [tags] tags = [tags]
except TypeError: except TypeError:
... pass
except KeyError: except KeyError:
... pass
try: try:
tags = xmpdata["xapmeta"]["RDF"]["Description"]["subject"]["Bag"]["li"] tags = xmpdata["xapmeta"]["RDF"]["Description"]["subject"]["Bag"]["li"]
if isinstance(tags, str): if isinstance(tags, str):
tags = [tags] tags = [tags]
except TypeError: except TypeError:
... pass
except KeyError: 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: if None in tags:
tags.remove(None) tags.remove(None)
return tags return tags
@@ -260,25 +348,23 @@ def process_image(item: str, folder: str, _args: Args, baseurl: str, metadata: d
dict[str, Any]: dictionary containing image details for HTML rendering. dict[str, Any]: dictionary containing image details for HTML rendering.
""" """
extsplit = os.path.splitext(item) extsplit = os.path.splitext(item)
if item not in metadata or _args.reread_metadata:
metadata[item] = get_image_info(item, folder)
sidecarfile = os.path.join(folder, item + ".xmp") sidecarfile = os.path.join(folder, item + ".xmp")
if os.path.exists(sidecarfile): if item not in metadata["images"] or _args.reread_metadata:
metadata["images"][item] = get_image_info(item, folder)
if _args.reread_sidecar and os.path.exists(sidecarfile):
logger.info("xmp sidecar file found", extra={"file": sidecarfile}) logger.info("xmp sidecar file found", extra={"file": sidecarfile})
try: try:
metadata[item]["tags"] = get_tags(sidecarfile) metadata["images"][item]["tags"] = get_tags(sidecarfile)
except Exception as e: except Exception as e:
logger.error(e) logger.error(e)
image = { image = {
"url": f"{_args.web_root_url}{baseurl}{urllib.parse.quote(item)}", "src": f"{_args.web_root_url}{baseurl}{urllib.parse.quote(item)}",
"thumbnail": f"{_args.web_root_url}.thumbnails/{baseurl}{urllib.parse.quote(item)}.jpg", "msrc": f"{_args.web_root_url}.thumbnails/{baseurl}{urllib.parse.quote(item)}.jpg",
"name": item, "name": item,
"width": metadata[item]["width"], "w": metadata["images"][item]["w"],
"height": metadata[item]["height"], "h": metadata["images"][item]["h"],
"tags": metadata[item]["tags"], "tags": metadata["images"][item]["tags"],
"exifdata": metadata[item].get("exifdata", ""),
"xmp": metadata[item].get("xmp", ""),
} }
path = os.path.join(_args.root_directory, ".thumbnails", baseurl, item + ".jpg") path = os.path.join(_args.root_directory, ".thumbnails", baseurl, item + ".jpg")
if not os.path.exists(path) or _args.regenerate_thumbnails: if not os.path.exists(path) or _args.regenerate_thumbnails:
@@ -296,10 +382,13 @@ def process_image(item: str, folder: str, _args: Args, baseurl: str, metadata: d
else: else:
logger.info("raw file found", extra={"file": file, "extension": _raw}) logger.info("raw file found", extra={"file": file, "extension": _raw})
image["raw"] = url image["raw"] = url
return image
metadata["images"][item].update(image)
return image, metadata
def generate_html(folder: str, title: str, _args: Args, raw: list[str], version: str, logo) -> None: def generate_html(folder: str, title: str, _args: Args, raw: list[str], version: str, logo: str) -> list[str]:
""" """
Generates HTML content for a folder of images. Generates HTML content for a folder of images.
@@ -320,10 +409,15 @@ def generate_html(folder: str, title: str, _args: Args, raw: list[str], version:
contains_files = False contains_files = False
images = [] images = []
subfolders = [] subfolders = []
subfoldertags = set()
foldername = folder.removeprefix(_args.root_directory) foldername = folder.removeprefix(_args.root_directory)
foldername = f"{foldername}/" if foldername else "" foldername = f"{foldername}/" if foldername else ""
baseurl = urllib.parse.quote(foldername) baseurl = urllib.parse.quote(foldername)
gone = [item for item in metadata["images"] if item not in items]
for gon in gone:
del metadata["images"][gon]
create_thumbnail_folder(foldername, _args.root_directory) create_thumbnail_folder(foldername, _args.root_directory)
logger.info("processing contents", extra={"folder": folder}) logger.info("processing contents", extra={"folder": folder})
@@ -331,11 +425,12 @@ def generate_html(folder: str, title: str, _args: Args, raw: list[str], version:
for item in tqdm(items, total=len(items), desc=f"Getting image infos - {folder}", unit="files", ascii=True, dynamic_ncols=True): for item in tqdm(items, total=len(items), desc=f"Getting image infos - {folder}", unit="files", ascii=True, dynamic_ncols=True):
if item not in EXCLUDES and not item.startswith("."): if item not in EXCLUDES and not item.startswith("."):
if os.path.isdir(os.path.join(folder, item)): if os.path.isdir(os.path.join(folder, item)):
process_subfolder(item, folder, baseurl, subfolders, _args, raw, version, logo) subfoldertags.update(process_subfolder(item, folder, baseurl, subfolders, _args, raw, version, logo))
else: else:
contains_files = True contains_files = True
if os.path.splitext(item)[1].lower() in _args.file_extensions: if os.path.splitext(item)[1].lower() in _args.file_extensions:
images.append(process_image(item, folder, _args, baseurl, metadata, raw)) img, metadata = process_image(item, folder, _args, baseurl, metadata, raw)
images.append(img)
if item == "info": if item == "info":
process_info_file(folder, item) process_info_file(folder, item)
if item == "LICENSE": if item == "LICENSE":
@@ -344,24 +439,31 @@ def generate_html(folder: str, title: str, _args: Args, raw: list[str], version:
for item in items: for item in items:
if item not in EXCLUDES and not item.startswith("."): if item not in EXCLUDES and not item.startswith("."):
if os.path.isdir(os.path.join(folder, item)): if os.path.isdir(os.path.join(folder, item)):
process_subfolder(item, folder, baseurl, subfolders, _args, raw, version, logo) subfoldertags.update(process_subfolder(item, folder, baseurl, subfolders, _args, raw, version, logo))
else: else:
contains_files = True contains_files = True
if os.path.splitext(item)[1].lower() in _args.file_extensions: if os.path.splitext(item)[1].lower() in _args.file_extensions:
images.append(process_image(item, folder, _args, baseurl, metadata, raw)) img, metadata = process_image(item, folder, _args, baseurl, metadata, raw)
images.append(img)
if item == "info": if item == "info":
process_info_file(folder, item) process_info_file(folder, item)
if item == "LICENSE": if item == "LICENSE":
process_license(folder, item) process_license(folder, item)
metadata["subfolders"] = subfolders
if _args.reverse_sort:
metadata["images"] = {key: metadata["images"][key] for key in sorted(metadata["images"], reverse=True)}
else:
metadata["images"] = {key: metadata["images"][key] for key in sorted(metadata["images"])}
update_metadata(metadata, folder) update_metadata(metadata, folder)
if should_generate_html(images, contains_files, _args): if should_generate_html(images, contains_files, _args):
create_html_file(folder, title, foldername, images, subfolders, _args, version, logo) subfoldertags = create_html_file(folder, title, foldername, images, subfolders, _args, version, logo, subfoldertags)
else: else:
if os.path.exists(os.path.join(folder, "index.html")): if os.path.exists(os.path.join(folder, "index.html")):
logger.info("removing existing index.html", extra={"folder": folder}) logger.info("removing existing index.html", extra={"folder": folder})
os.remove(os.path.join(folder, "index.html")) os.remove(os.path.join(folder, "index.html"))
return subfoldertags
def create_thumbnail_folder(foldername: str, root_directory: str) -> None: def create_thumbnail_folder(foldername: str, root_directory: str) -> None:
@@ -378,7 +480,7 @@ def create_thumbnail_folder(foldername: str, root_directory: str) -> None:
os.mkdir(thumbnails_path) os.mkdir(thumbnails_path)
def process_subfolder(item: str, folder: str, baseurl: str, subfolders: list[dict[str, str | None]], _args: Args, raw: list[str], version: str, logo: str) -> None: def process_subfolder(item: str, folder: str, baseurl: str, subfolders: list[dict[str, str | None]], _args: Args, raw: list[str], version: str, logo: str) -> list[str]:
""" """
Processes a subfolder. Processes a subfolder.
@@ -404,10 +506,12 @@ def process_subfolder(item: str, folder: str, baseurl: str, subfolders: list[dic
else: else:
thumb = f"{_args.web_root_url}.thumbnails/{baseurl}{urllib.parse.quote(item)}/{urllib.parse.quote(thumbitems[0])}.jpg" thumb = f"{_args.web_root_url}.thumbnails/{baseurl}{urllib.parse.quote(item)}/{urllib.parse.quote(thumbitems[0])}.jpg"
subfolders.append({"url": subfolder_url, "name": item, "thumb": thumb})
if item not in _args.exclude_folders: if item not in _args.exclude_folders:
if not any(fnmatch.fnmatchcase(os.path.join(folder, item), exclude) for exclude in _args.exclude_folders): if not any(fnmatch.fnmatchcase(os.path.join(folder, item), exclude) for exclude in _args.exclude_folders):
generate_html(os.path.join(folder, item), os.path.join(folder, item).removeprefix(_args.root_directory), _args, raw, version, logo) subfolders.append({"url": subfolder_url, "name": item, "thumb": thumb, "metadata": f"{_args.web_root_url}{baseurl}{urllib.parse.quote(item)}/.metadata.json"})
return generate_html(os.path.join(folder, item), os.path.join(folder, item).removeprefix(_args.root_directory), _args, raw, version, logo)
subfolders.append({"url": subfolder_url, "name": item, "thumb": thumb, "metadata": None})
return []
def process_license(folder: str, item: str) -> None: def process_license(folder: str, item: str) -> None:
@@ -452,7 +556,9 @@ def should_generate_html(images: list[dict[str, Any]], contains_files, _args: Ar
return images or (_args.use_fancy_folders and not contains_files) or (_args.use_fancy_folders and _args.ignore_other_files) return images or (_args.use_fancy_folders and not contains_files) or (_args.use_fancy_folders and _args.ignore_other_files)
def create_html_file(folder: str, title: str, foldername: str, images: list[dict[str, Any]], subfolders: list[dict[str, str]], _args: Args, version: str, logo: str) -> None: def create_html_file(
folder: str, title: str, foldername: str, images: list[dict[str, Any]], subfolders: list[dict[str, str]], _args: Args, version: str, logo: str, subfoldertags: list[str]
) -> list[str]:
""" """
Creates the HTML file using the template. Creates the HTML file using the template.
@@ -485,9 +591,9 @@ def create_html_file(folder: str, title: str, foldername: str, images: list[dict
alltags = set() alltags = set()
for img in images: for img in images:
for tag in img["tags"]: alltags.update(img["tags"])
alltags.add(tag)
alltags = sorted(alltags) alltags.update(set(subfoldertags))
folder_info = info.get(urllib.parse.quote(folder), "").split("\n") folder_info = info.get(urllib.parse.quote(folder), "").split("\n")
_info = [i for i in folder_info if len(i) > 1] if folder_info else None _info = [i for i in folder_info if len(i) > 1] if folder_info else None
@@ -531,19 +637,20 @@ def create_html_file(folder: str, title: str, foldername: str, images: list[dict
header=header, header=header,
license=license_info, license=license_info,
subdirectories=subfolders, subdirectories=subfolders,
images=images,
info=_info, info=_info,
webmanifest=_args.generate_webmanifest, webmanifest=_args.generate_webmanifest,
version=version, version=version,
logo=logo, logo=logo,
licensefile=license_url, licensefile=license_url,
tags=alltags, tags=parse_hierarchical_tags(alltags),
) )
with open(html_file, "w", encoding="utf-8") as f: with open(html_file, "w", encoding="utf-8") as f:
logger.info("writing html file", extra={"path": html_file}) logger.info("writing html file", extra={"path": html_file})
f.write(content) f.write(content)
return sorted(alltags)
def list_folder(folder: str, title: str, _args: Args, raw: list[str], version: str, logo: str) -> list[tuple[str, str, str]]: def list_folder(folder: str, title: str, _args: Args, raw: list[str], version: str, logo: str) -> list[tuple[str, str, str]]:
""" """

View File

@@ -52,7 +52,11 @@
background-color: var(--color2); background-color: var(--color2);
} }
.tagentry:hover { .tagentry label:hover {
background-color: var(--color7);
}
.tagentry .tagtoggle:hover {
background-color: var(--color4); background-color: var(--color4);
} }

View File

@@ -1,3 +1,25 @@
{%- macro render_tags(tag_tree, parent) -%}
{%- for key, value in tag_tree.items() %}
<li class="tagentry">
<div class="tagflex">
<label class="tag" title="{{ key }}" id="{{ parent }}|{{ key }}">
<input type="checkbox" class="tagcheckbox" />{{ key }}
</label>{% if value %} <span class="tagtoggle" data-tagid="{{ parent }}|{{ key }}">
<svg width="1em" height="1em" viewBox="0 0 129.87601 129.87624">
<g id="layer1" transform="translate(-33.816833,-52.685642)">
<path stroke="currentColor" style="fill:none;stroke-width:20;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
d="M 54.476483,95.484647 98.754836,139.76308 143.03319,95.484647" id="path1" />
</g>
</svg></span>{% endif %}
</div>
{%- if value %}
<ol class="tagentryparent">
{{ render_tags(value, parent + '|' + key) }}
</ol>
{%- endif %}
</li><br>
{%- endfor %}
{%- endmacro -%}
<!DOCTYPE html> <!DOCTYPE html>
<html lang="en"> <html lang="en">
@@ -21,12 +43,10 @@
<link rel="preload" href="{{ root }}.static/pswp/default-skin/default-skin.css" as="style"> <link rel="preload" href="{{ root }}.static/pswp/default-skin/default-skin.css" as="style">
<link rel="modulepreload" href="{{ root }}.static/pswp/photoswipe.min.js"> <link rel="modulepreload" href="{{ root }}.static/pswp/photoswipe.min.js">
<link rel="modulepreload" href="{{ root }}.static/pswp/photoswipe-ui-default.min.js"> <link rel="modulepreload" href="{{ root }}.static/pswp/photoswipe-ui-default.min.js">
{%- if images %}
<link rel="stylesheet" href="{{ root }}.static/pswp/photoswipe.css"> <link rel="stylesheet" href="{{ root }}.static/pswp/photoswipe.css">
<link rel="stylesheet" href="{{ root }}.static/pswp/default-skin/default-skin.css"> <link rel="stylesheet" href="{{ root }}.static/pswp/default-skin/default-skin.css">
<script src="{{ root }}.static/pswp/photoswipe.min.js"></script> <script src="{{ root }}.static/pswp/photoswipe.min.js"></script>
<script src="{{ root }}.static/pswp/photoswipe-ui-default.min.js"></script> <script src="{{ root }}.static/pswp/photoswipe-ui-default.min.js"></script>
{%- endif %}
</head> </head>
<body> <body>
@@ -49,24 +69,30 @@
<li class="title"><span class="header">{{ header }}</span></li> <li class="title"><span class="header">{{ header }}</span></li>
</div> </div>
<div class="navright"> <div class="navright">
{%- if tags|length > 0 %} {% if tags %}
<li class="tooltip"><a>Filter by Tags</a> <li class="tooltip">
<a id="tagtogglelink">Filter by Tags <svg width="0.8em" height="0.8em" viewBox="0 0 129.87601 129.87624">
<g id="layer1" transform="translate(-33.816833,-52.685642)">
<path stroke="currentColor" style="fill:none;stroke-width:20;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
d="M 54.476483,95.484647 98.754836,139.76308 143.03319,95.484647" id="path1" />
</g>
</svg></a>
<ol class="tooltiptext tagdropdown" id="tagdropdown"> <ol class="tooltiptext tagdropdown" id="tagdropdown">
{%- for tag in tags -%} <span class="tagentry">
<li class="tagentry"><label onclick="filter()"><input type="checkbox" />{{ tag }}</label></li><br /> <label onclick="recursive()">
{%- endfor -%} <input type="checkbox" id="recursive" />recursive filter
</label>
</span>
{{ render_tags(tags, '') }}
</ol> </ol>
</li> </li>
{%- endif %} {% endif %}
{%- if licensefile %} {%- if licensefile %}
<li class="license"><a href="{{ licensefile }}">License</a></li> <li class="license"><a href="{{ licensefile }}">License</a></li>
{%- endif %} {%- endif %}
</div> </div>
</ol> </ol>
{% if subdirectories %} {% if subdirectories %}
{%- for subdirectory in subdirectories %}
<link rel="preload" href="{{ subdirectory.url }}/index.html" type="text/html">
{%- endfor %}
<div class="folders"> <div class="folders">
{%- for subdirectory in subdirectories %} {%- for subdirectory in subdirectories %}
<a href="{{ subdirectory.url }}"> <a href="{{ subdirectory.url }}">
@@ -82,27 +108,8 @@
</div> </div>
{%- endif %} {%- endif %}
</div> </div>
{% if images %}
{%- set ns = namespace(count = 0) -%}
<div class="row" id="imagelist"> <div class="row" id="imagelist">
{%- 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> </div>
{%- endif %}
{% if license %} {% if license %}
{%- if 'CC' in license.type %} {%- if 'CC' in license.type %}
<div class="footer" xmlns:cc="http://creativecommons.org/ns#" xmlns:dct="http://purl.org/dc/terms/"> <div class="footer" xmlns:cc="http://creativecommons.org/ns#" xmlns:dct="http://purl.org/dc/terms/">
@@ -123,17 +130,16 @@
{%- endif %} {%- endif %}
<span class="attribution">Made with <a href="https://github.com/greflm13/StaticGalleryBuilder" target="_blank" rel="noopener noreferrer">StaticGalleryBuilder {{ version }}</a> by <a <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> 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> </div>
{%- endif %} {%- endif %}
{%- else %} {%- else %}
<div class="footer"> <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 <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> 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> </div>
{%- endif %} {%- endif %}
{% if images %}
<div class="pswp" tabindex="-1" role="dialog" aria-hidden="true"> <div class="pswp" tabindex="-1" role="dialog" aria-hidden="true">
<div class="pswp__bg"></div> <div class="pswp__bg"></div>
<div class="pswp__scroll-wrap"> <div class="pswp__scroll-wrap">
@@ -171,33 +177,172 @@
</div> </div>
</div> </div>
<script> <script>
var pswpElement = document.querySelectorAll('.pswp')[0]; const pswpElement = document.querySelectorAll('.pswp')[0];
var items = [ const re = /pid=(\d+)/;
{%- for image in images %} const filterre = /#(.*)/;
{%- if image.exifdata.DateTime %} const recursere = /\?recursive/;
{ src: "{{ image.url }}", w: {{ image.width }}, h: {{ image.height }}, msrc: "{{ image.thumbnail }}", tags: "{{ image.tags }}", title: "Captured: {{ image.exifdata.DateTime }}" }, let items = [];
{%- else %} let shown = [];
{ src: "{{ image.url }}", w: {{ image.width }}, h: {{ image.height }}, msrc: "{{ image.thumbnail }}", tags: "{{ image.tags }}" }, let subfolders = [];
{%- endif %} let controllers = {};
{%- endfor %} let tagdropdownshown = false;
];
var re = /pid=(\d+)/; function requestMetadata() {
var controllers = {} fetch(".metadata.json").then(response => {
if (!response.ok) {
throw new Error(`HTTP error! Status: ${response.status}`);
}
return response.json();
})
.then(data => {
items = Object.values(data.images);
subfolders = data.subfolders;
if (filterre.test(window.location.href)) {
const selected = window.location.href.match(filterre)[1].split(",");
setFilter(selected);
}
if (recursere.test(window.location.href)) {
document.getElementById("recursive").checked = true;
recursive();
}
filter();
if (re.test(window.location.href)) {
const pid = window.location.href.match(re)[1];
openSwipe(parseInt(pid));
}
})
.catch(error => console.error('Failed to fetch data:', error));
}
function setupTagHandlers() {
const tagContainer = document.getElementById("tagdropdown");
if (tagContainer == null) {
return;
}
tagContainer.addEventListener("change", debounce(filter, 150));
tagContainer.addEventListener("click", function (event) {
const toggle = event.target.closest(".tagtoggle");
if (toggle) {
event.stopPropagation();
const tagid = toggle.dataset.toggleid;
toggleTag(tagid);
}
});
}
function toggleTag(tagid) {
const tag = document.getElementById(tagid);
const ol = tag?.closest(".tagentry")?.querySelector(".tagentryparent");
const svg = tag?.parentElement.querySelector(".tagtoggle svg");
if (!ol || !svg) return;
ol.classList.toggle("show");
svg.style.transform = ol.classList.contains("show") ? "rotate(180deg)" : "rotate(0deg)";
}
function debounce(fn, delay) {
let timeoutId;
return function (...args) {
clearTimeout(timeoutId);
timeoutId = setTimeout(() => fn.apply(this, args), delay);
};
}
function openSwipe(img) { function openSwipe(img) {
var options = { const options = {
index: img index: img
}; };
var gallery = new PhotoSwipe(pswpElement, PhotoSwipeUI_Default, items, options); const gallery = new PhotoSwipe(pswpElement, PhotoSwipeUI_Default, shown, options);
gallery.init(); gallery.init();
} }
if (re.test(window.location.href)) { async function recursive(sub = undefined) {
var pid = window.location.href.match(re)[1]; const curr = window.location.href.split("#");
openSwipe(parseInt(pid)); const content = document.getRootNode().innerHTML;
const title = document.title;
const isChecked = document.getElementById("recursive").checked;
const folders = document.querySelector(".folders");
if (!isChecked) {
if (folders) folders.style.display = "";
window.history.replaceState({ html: content, pageTitle: title }, "", curr[0].split("?")[0] + "#" + curr[1]);
requestMetadata();
return;
}
if (folders) folders.style.display = "none";
window.history.replaceState({ html: content, pageTitle: title }, "", curr[0].split("?")[0] + "?recursive#" + curr[1]);
const visited = new Set();
const existingItems = new Set();
const newItems = [];
try {
const response = await fetch(".metadata.json");
if (!response.ok) throw new Error(`HTTP error! Status: ${response.status}`);
const data = await response.json();
items = [];
subfolders = data.subfolders || [];
sub = subfolders;
for (const image of Object.values(data.images || {})) {
newItems.push(image);
existingItems.add(image.src);
}
} catch (error) {
console.error("Failed to fetch base .metadata.json:", error);
return;
}
async function fetchFoldersRecursively(folderList) {
if (!Array.isArray(folderList)) return;
const nextLevel = [];
await Promise.all(folderList.map(async (folder) => {
if (!folder || !folder.metadata || visited.has(folder.url)) return;
visited.add(folder.url);
if (!folder.metadata) return;
try {
const response = await fetch(folder.metadata);
if (!response.ok) throw new Error(`Failed to fetch ${folder.metadata}`);
const data = await response.json();
for (const image of Object.values(data.images || {})) {
if (!existingItems.has(image.src)) {
newItems.push(image);
existingItems.add(image.src);
}
}
if (Array.isArray(data.subfolders)) {
nextLevel.push(...data.subfolders);
}
} catch (error) {
console.error("Failed to fetch folder metadata:", error);
}
}));
if (nextLevel.length > 0) {
await fetchFoldersRecursively(nextLevel);
}
}
await fetchFoldersRecursively(sub);
items = [...newItems];
filter();
} }
let totopbutton = document.getElementById("totop"); const totopbutton = document.getElementById("totop");
window.onscroll = function () { scrollFunction() }; window.onscroll = function () { scrollFunction() };
@@ -213,6 +358,23 @@
window.scrollTo({ top: 0, behavior: 'smooth' }) window.scrollTo({ top: 0, behavior: 'smooth' })
} }
function updateImageList() {
let str = ""
let imagelist = document.getElementById("imagelist");
shown.forEach((item, index) => {
str += '<div class="column"><figure><img src="' + item.msrc + '" onclick="openSwipe(' + index + ')" onmouseover="prefetch(' + index + ')" onmouseleave="cancel(' + index + ')" /><figcaption class="caption">' + item.name;
if (item.tiff != "" & item.tiff != undefined) {
str += ' <a href="' + item.tiff + '">TIFF</a>';
}
if (item.raw != "" & item.raw != undefined) {
str += ' <a href="' + item.raw + '">RAW</a>';
}
str += '</figcaption></figure></div>';
});
imagelist.innerHTML = str;
}
function prefetch(img) { function prefetch(img) {
const controller = new AbortController() const controller = new AbortController()
const signal = controller.signal const signal = controller.signal
@@ -230,38 +392,113 @@
delete controllers[img]; delete controllers[img];
} }
{%- if tags|length > 0 %}
function filter() { function filter() {
var selected_tags = []; shown = [];
var tagdropdown, imagelist, figures, i, j, tags, incl; let isRecursiveChecked = false;
tagdropdown = document.getElementById("tagdropdown").getElementsByTagName("li");
for (i = 0; i < tagdropdown.length; i++) { const curr = window.location.href.split("#")[0] + "#";
if (tagdropdown[i].firstChild.firstChild.checked) { const path = decodeURIComponent(window.location.href.split("#")[0].replace("index.html", ""))
selected_tags.push([tagdropdown[i].innerText])
const selected_tags = [];
const tagcheckboxes = document.querySelectorAll("#tagdropdown input[class='tagcheckbox']:checked");
tagcheckboxes.forEach((checkbox) => {
let tag = checkbox.parentElement.id.trim().substring(1);
if (checkbox.parentElement.parentElement.children.length > 1) {
tag += "|"
} }
} selected_tags.push(tag);
imagelist = document.getElementById("imagelist"); });
figures = imagelist.getElementsByTagName("div");
for (i = 0; i < figures.length; i++) { const urltags = selected_tags.join(",");
tags = items[i].tags;
incl = true; try {
for (j = 0; j < selected_tags.length; j++) { isRecursiveChecked = document.getElementById("recursive").checked;
if (tags.indexOf(selected_tags[j]) == -1) { } catch { }
incl = false;
for (const item of items) {
const tags = item.tags || [];
const include = selected_tags.every(selected => {
const isParent = selected.endsWith('|');
if (isParent) {
return tags.some(t => t.startsWith(selected));
} else {
return tags.includes(selected);
}
});
if (include || selected_tags.length === 0) {
if (!isRecursiveChecked) {
if (decodeURIComponent(item.src.replace(item.name, "")) == path) {
shown.push(item);
}
} else {
shown.push(item);
} }
} }
if (incl || selected_tags == []) {
figures[i].style.display = "";
} else {
figures[i].style.display = "none";
}
} }
updateImageList();
window.location.href = curr + urltags;
} }
filter() function setFilter(selected) {
{%- endif %} const tagcheckboxes = document.querySelectorAll("#tagdropdown input[class='tagcheckbox']");
selected.forEach((tag) => {
tagcheckboxes.forEach((checkbox) => {
if (checkbox.parentElement.id.trim().substring(1).replace(" ", "%20") == tag) {
checkbox.checked = true;
}
});
});
}
function setupDropdownToggle() {
const toggleLink = document.getElementById("tagtogglelink");
const dropdown = document.getElementById("tagdropdown");
if (toggleLink == null) {
return;
}
toggleLink.addEventListener("click", function (event) {
event.stopPropagation();
const svg = this.querySelector("svg");
dropdown.classList.toggle("show");
if (svg) svg.style.transform = dropdown.classList.contains("show") ? "rotate(180deg)" : "rotate(0deg)";
tagdropdownshown = dropdown.classList.contains("show");
});
document.addEventListener("click", function (event) {
if (!dropdown.contains(event.target) && !toggleLink.contains(event.target)) {
dropdown.classList.remove("show");
tagdropdownshown = false;
const svg = toggleLink.querySelector("svg");
if (svg) svg.style.transform = "rotate(0deg)";
}
});
}
function onLoad() {
document.querySelectorAll('.tagtoggle').forEach(toggle => {
toggle.addEventListener('mouseup', function (event) {
event.stopPropagation();
const tagid = this.getAttribute('data-tagid');
toggleTag(tagid);
});
});
requestMetadata();
setupDropdownToggle();
setupTagHandlers();
const recurseEl = document.getElementById("recursive")
if (recurseEl != null) { recurseEl.addEventListener("change", debounce(recursive, 150)); }
}
window.addEventListener ?
window.addEventListener("load", onLoad, false) :
window.attachEvent && window.attachEvent("onload", onLoad);
</script> </script>
{%- endif %}
</body> </body>
</html> </html>

View File

@@ -54,14 +54,14 @@
{%- endif %} {%- endif %}
<span class="attribution">Made with <a href="https://github.com/greflm13/StaticGalleryBuilder" target="_blank" rel="noopener noreferrer">StaticGalleryBuilder {{ version }}</a> by <a <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> 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> </div>
{%- endif %} {%- endif %}
{%- else %} {%- else %}
<div class="footer"> <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 <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> 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> </div>
{%- endif %} {%- endif %}
</body> </body>

View File

@@ -2,6 +2,6 @@
<x:xmpmeta x:xmptk="XMP Core 4.4.0-Exiv2" xmlns:x="adobe:ns:meta/"> <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: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"> <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></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>|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></lr:hierarchicalSubject></rdf:Description> <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> </rdf:RDF>
</x:xmpmeta> </x:xmpmeta>

View File

@@ -1,7 +1,39 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<x:xmpmeta x:xmptk="XMP Core 4.4.0-Exiv2" xmlns:x="adobe:ns:meta/"> <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: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"> <rdf:Description rdf:about="" xmlns:dc="http://purl.org/dc/elements/1.1/"
<dc:subject><rdf:Bag><rdf:li></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>|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></lr:hierarchicalSubject></rdf:Description> xmlns:exif="http://ns.adobe.com/exif/1.0/" xmlns:lr="http://ns.adobe.com/lightroom/1.0/"
</rdf:RDF> 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:li>train</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:li>st|train</rdf:li>
</rdf:Bag>
</lr:hierarchicalSubject>
</rdf:Description>
</rdf:RDF>
</x:xmpmeta> </x:xmpmeta>

View File

@@ -2,6 +2,6 @@
<x:xmpmeta x:xmptk="XMP Core 4.4.0-Exiv2" xmlns:x="adobe:ns:meta/"> <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: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"> <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></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>|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></lr:hierarchicalSubject></rdf:Description> <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> </rdf:RDF>
</x:xmpmeta> </x:xmpmeta>

View File

@@ -1,7 +1,49 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<x:xmpmeta x:xmptk="XMP Core 4.4.0-Exiv2" xmlns:x="adobe:ns:meta/"> <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: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"> <rdf:Description rdf:about="" xmlns:dc="http://purl.org/dc/elements/1.1/"
<dc:subject><rdf:Bag><rdf:li></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>|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></lr:hierarchicalSubject></rdf:Description> xmlns:exif="http://ns.adobe.com/exif/1.0/" xmlns:lr="http://ns.adobe.com/lightroom/1.0/"
</rdf:RDF> 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:li>train</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:li>st|train</rdf:li>
</rdf:Bag>
</lr:hierarchicalSubject>
</rdf:Description>
</rdf:RDF>
</x:xmpmeta> </x:xmpmeta>

View File

@@ -1,7 +1,35 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<x:xmpmeta x:xmptk="XMP Core 4.4.0-Exiv2" xmlns:x="adobe:ns:meta/"> <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: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"> <rdf:Description rdf:about="" xmlns:dc="http://purl.org/dc/elements/1.1/"
<dc:subject><rdf:Bag><rdf:li></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>|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></lr:hierarchicalSubject></rdf:Description> xmlns:exif="http://ns.adobe.com/exif/1.0/" xmlns:lr="http://ns.adobe.com/lightroom/1.0/"
</rdf:RDF> 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>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|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> </x:xmpmeta>

View File

@@ -2,6 +2,6 @@
<x:xmpmeta x:xmptk="XMP Core 4.4.0-Exiv2" xmlns:x="adobe:ns:meta/"> <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: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"> <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></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>|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></lr:hierarchicalSubject></rdf:Description> <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> </rdf:RDF>
</x:xmpmeta> </x:xmpmeta>

View File

Before

Width:  |  Height:  |  Size: 3.5 MiB

After

Width:  |  Height:  |  Size: 3.5 MiB

View File

@@ -0,0 +1,30 @@
<?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|sky|night sky</rdf:li>
</rdf:Bag>
</lr:hierarchicalSubject>
</rdf:Description>
</rdf:RDF>
</x:xmpmeta>

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.3 MiB

View File

@@ -0,0 +1,25 @@
<?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>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|fly</rdf:li>
<rdf:li>st|sky</rdf:li>
</rdf:Bag>
</lr:hierarchicalSubject>
</rdf:Description>
</rdf:RDF>
</x:xmpmeta>

View File

@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<x:xmpmeta x:xmptk="XMP Core 4.4.0-Exiv2" xmlns:x="adobe:ns:meta/"> <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: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"> <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></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>|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></lr:hierarchicalSubject></rdf:Description> <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> </rdf:RDF>
</x:xmpmeta> </x:xmpmeta>

View File

@@ -97,7 +97,11 @@ body {
background-color: var(--color6); background-color: var(--color6);
} }
.tagentry:hover { .tagentry label:hover {
background-color: var(--color3);
}
.tagentry .tagtoggle:hover {
background-color: var(--color3); background-color: var(--color3);
} }

View File

@@ -96,7 +96,11 @@ body {
background-color: var(--color3); background-color: var(--color3);
} }
.tagentry:hover { .tagentry label:hover {
background-color: var(--color7);
}
.tagentry .tagtoggle:hover {
background-color: var(--color7); background-color: var(--color7);
} }

View File

@@ -74,7 +74,11 @@
background-color: var(--bcolor1); background-color: var(--bcolor1);
} }
.tagentry:hover { .tagentry label:hover {
background-color: var(--bcolor3);
}
.tagentry .tagtoggle:hover {
background-color: var(--bcolor3); background-color: var(--bcolor3);
} }

View File

@@ -74,7 +74,11 @@
background-color: var(--bcolor1); background-color: var(--bcolor1);
} }
.tagentry:hover { .tagentry label:hover {
background-color: var(--bcolor3);
}
.tagentry .tagtoggle:hover {
background-color: var(--bcolor3); background-color: var(--bcolor3);
} }

View File

@@ -79,7 +79,11 @@
font-family: "Playfair Display", serif; font-family: "Playfair Display", serif;
} }
.tagentry:hover { .tagentry label:hover {
background-color: var(--color3);
}
.tagentry .tagtoggle:hover {
background-color: var(--color3); background-color: var(--color3);
} }

View File

@@ -73,7 +73,11 @@
background-color: var(--bcolor2); background-color: var(--bcolor2);
} }
.tagentry:hover { .tagentry label:hover {
background-color: var(--bcolor4);
}
.tagentry .tagtoggle:hover {
background-color: var(--bcolor4); background-color: var(--bcolor4);
} }

View File

@@ -79,7 +79,11 @@
font-family: "Nunito", sans-serif; font-family: "Nunito", sans-serif;
} }
.tagentry:hover { .tagentry label:hover {
background-color: var(--color4);
}
.tagentry .tagtoggle:hover {
background-color: var(--color4); background-color: var(--color4);
} }

View File

@@ -73,7 +73,11 @@
background-color: var(--bcolor2); background-color: var(--bcolor2);
} }
.tagentry:hover { .tagentry label:hover {
background-color: var(--bcolor4);
}
.tagentry .tagtoggle:hover {
background-color: var(--bcolor4); background-color: var(--bcolor4);
} }

View File

@@ -52,7 +52,11 @@
background-color: var(--color3); background-color: var(--color3);
} }
.tagentry:hover { .tagentry label:hover {
background-color: var(--color4);
}
.tagentry .tagtoggle:hover {
background-color: var(--color4); background-color: var(--color4);
} }

View File

@@ -52,7 +52,11 @@
background-color: var(--color2); background-color: var(--color2);
} }
.tagentry:hover { .tagentry label:hover {
background-color: var(--color4);
}
.tagentry .tagtoggle:hover {
background-color: var(--color4); background-color: var(--color4);
} }

View File

@@ -73,7 +73,11 @@
background-color: var(--bcolor2); background-color: var(--bcolor2);
} }
.tagentry:hover { .tagentry label:hover {
background-color: var(--bcolor4);
}
.tagentry .tagtoggle:hover {
background-color: var(--bcolor4); background-color: var(--bcolor4);
} }

View File

@@ -72,7 +72,11 @@
background-color: var(--color3); background-color: var(--color3);
} }
.tagentry:hover { .tagentry label:hover {
background-color: var(--color2);
}
.tagentry .tagtoggle:hover {
background-color: var(--color2); background-color: var(--color2);
} }

View File

@@ -55,7 +55,11 @@
background-color: var(--bcolor2); background-color: var(--bcolor2);
} }
.tagentry:hover { .tagentry label:hover {
background-color: var(--bcolor3);
}
.tagentry .tagtoggle:hover {
background-color: var(--bcolor3); background-color: var(--bcolor3);
} }

View File

@@ -76,7 +76,11 @@
background-color: var(--bcolor2); background-color: var(--bcolor2);
} }
.tagentry:hover { .tagentry label:hover {
background-color: var(--bcolor4);
}
.tagentry .tagtoggle:hover {
background-color: var(--bcolor4); background-color: var(--bcolor4);
} }

View File

@@ -79,7 +79,11 @@
font-family: "Lora", serif; font-family: "Lora", serif;
} }
.tagentry:hover { .tagentry label:hover {
background-color: var(--bcolor3);
}
.tagentry .tagtoggle:hover {
background-color: var(--bcolor3); background-color: var(--bcolor3);
} }

View File

@@ -80,7 +80,11 @@
background-color: var(--color4); background-color: var(--color4);
} }
.tagentry:hover { .tagentry label:hover {
background-color: var(--color3);
}
.tagentry .tagtoggle:hover {
background-color: var(--color3); background-color: var(--color3);
} }

View File

@@ -80,7 +80,11 @@
font-family: "Roboto", sans-serif; font-family: "Roboto", sans-serif;
} }
.tagentry:hover { .tagentry label:hover {
background-color: var(--bcolor3);
}
.tagentry .tagtoggle:hover {
background-color: var(--bcolor3); background-color: var(--bcolor3);
color: var(--bcolor2); color: var(--bcolor2);
} }

View File

@@ -74,7 +74,11 @@
background-color: var(--bcolor2); background-color: var(--bcolor2);
} }
.tagentry:hover { .tagentry label:hover {
background-color: var(--bcolor4);
}
.tagentry .tagtoggle:hover {
background-color: var(--bcolor4); background-color: var(--bcolor4);
} }

View File

@@ -88,7 +88,11 @@
font-family: "Montserrat", sans-serif; font-family: "Montserrat", sans-serif;
} }
.tagentry:hover { .tagentry label:hover {
background-color: var(--color2);
}
.tagentry .tagtoggle:hover {
background-color: var(--color2); background-color: var(--color2);
} }