mirror of
https://github.com/greflm13/StaticGalleryBuilder.git
synced 2026-02-05 11:09:26 +00:00
Compare commits
12 Commits
v2.8.6
...
4ef1b429f2
| Author | SHA1 | Date | |
|---|---|---|---|
| 4ef1b429f2 | |||
| b8314c0e3d | |||
| 60f3ca1f20 | |||
| bc519ac5d0 | |||
| b0c1b2ce48 | |||
| faa283efa3 | |||
| ce70aa7bd9 | |||
| 59c7cfd406 | |||
| cfe1585c39 | |||
| 57b6b56388 | |||
| 2c6f8fbcb7 | |||
| 30eb1ed8df |
2
.github/workflows/build-release.yml
vendored
2
.github/workflows/build-release.yml
vendored
@@ -8,7 +8,7 @@ jobs:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: '3.x'
|
||||
python-version: '3.12'
|
||||
- name: Install Dependencies
|
||||
run: pip install -r requirements.txt
|
||||
- name: Build Package
|
||||
|
||||
@@ -103,3 +103,7 @@ To generate a web manifest file:
|
||||
## License
|
||||
|
||||
This project is licensed under the AGPL-3.0 License. See the [LICENSE](LICENSE) file for details.
|
||||
|
||||
## Star History
|
||||
|
||||
[](https://www.star-history.com/#greflm13/StaticGalleryBuilder&type=date&legend=top-left)
|
||||
|
||||
22
builder.py
22
builder.py
@@ -37,8 +37,8 @@ NOT_LIST = ["*/Galleries/*", "Archives"]
|
||||
|
||||
args = parse_arguments(VERSION)
|
||||
|
||||
lock_file = os.path.join(args.root_directory, ".lock")
|
||||
if os.path.exists(lock_file):
|
||||
LOCKFILE = os.path.join(args.root_directory, ".lock")
|
||||
if os.path.exists(LOCKFILE):
|
||||
print("Another instance of this program is running.")
|
||||
sys.exit()
|
||||
else:
|
||||
@@ -155,7 +155,7 @@ def generate_thumbnail(arguments: tuple[str, str, str]) -> None:
|
||||
imgrgb = imgfile.convert("RGB")
|
||||
img = ImageOps.exif_transpose(imgrgb)
|
||||
img.thumbnail((512, 512))
|
||||
img.save(path, "JPEG", quality=75, optimize=True, mode="RGB")
|
||||
img.save(path, "JPEG", quality=50, optimize=True, mode="RGB", subsampling=2)
|
||||
except OSError:
|
||||
logger.error("Failed to generate thumbnail for %s", item, extra={"path": image})
|
||||
print(f"Failed to generate thumbnail for {image}")
|
||||
@@ -168,12 +168,13 @@ def main(args) -> None:
|
||||
"""
|
||||
Main function to process images and generate a static image hosting website.
|
||||
"""
|
||||
thumbnails: list[tuple[str, str, str, bool]] = []
|
||||
thumbnails: list[tuple[str, str, str]] = []
|
||||
|
||||
args, raw = init_globals(args, RAW_EXTENSIONS)
|
||||
thumbdir = os.path.join(args.root_directory, ".thumbnails")
|
||||
|
||||
try:
|
||||
Path(lock_file).touch()
|
||||
Path(LOCKFILE).touch()
|
||||
logger.info("starting builder", extra={"version": VERSION, "arguments": args})
|
||||
|
||||
logger.info("getting logo from sorogon.eu")
|
||||
@@ -195,10 +196,10 @@ def main(args) -> None:
|
||||
logger.warning("reread metadata flag is set to true, all image metadata will be reread")
|
||||
if args.regenerate_thumbnails:
|
||||
logger.warning("regenerate thumbnails flag is set to true, all thumbnails will be regenerated")
|
||||
if os.path.exists(os.path.join(args.root_directory, ".thumbnails")):
|
||||
if os.path.exists(thumbdir):
|
||||
logger.info("removing old thumbnails folder")
|
||||
shutil.rmtree(os.path.join(args.root_directory, ".thumbnails"))
|
||||
os.makedirs(os.path.join(args.root_directory, ".thumbnails"), exist_ok=True)
|
||||
shutil.rmtree(thumbdir)
|
||||
os.makedirs(thumbdir, exist_ok=True)
|
||||
|
||||
copy_static_files(args)
|
||||
icons(args)
|
||||
@@ -229,8 +230,11 @@ def main(args) -> None:
|
||||
dynamic_ncols=True,
|
||||
):
|
||||
pass
|
||||
except Exception as e:
|
||||
logger.critical("an unhandled exception occurred: %s", str(e), exc_info=True)
|
||||
print(f"An unhandled exception occurred: {str(e)}")
|
||||
finally:
|
||||
os.remove(lock_file)
|
||||
os.remove(LOCKFILE)
|
||||
logger.info("finished builder", extra={"version": VERSION})
|
||||
|
||||
|
||||
|
||||
3
example.config
Normal file
3
example.config
Normal file
@@ -0,0 +1,3 @@
|
||||
root-directory = /path/to/webroot
|
||||
site-title = Website Title
|
||||
web-root-url = https://www.example.com
|
||||
192
help.svg
192
help.svg
@@ -1,4 +1,4 @@
|
||||
<svg class="rich-terminal" viewBox="0 0 1482 977.1999999999999" xmlns="http://www.w3.org/2000/svg">
|
||||
<svg class="rich-terminal" viewBox="0 0 1482 1074.8" xmlns="http://www.w3.org/2000/svg">
|
||||
<!-- Generated with Rich https://www.textualize.io -->
|
||||
<style>
|
||||
|
||||
@@ -19,191 +19,207 @@
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
.terminal-1232074479-matrix {
|
||||
.terminal-1915255058-matrix {
|
||||
font-family: Fira Code, monospace;
|
||||
font-size: 20px;
|
||||
line-height: 24.4px;
|
||||
font-variant-east-asian: full-width;
|
||||
}
|
||||
|
||||
.terminal-1232074479-title {
|
||||
.terminal-1915255058-title {
|
||||
font-size: 18px;
|
||||
font-weight: bold;
|
||||
font-family: arial;
|
||||
}
|
||||
|
||||
.terminal-1232074479-r1 { fill: #ff8700 }
|
||||
.terminal-1232074479-r2 { fill: #c5c8c6 }
|
||||
.terminal-1232074479-r3 { fill: #808080 }
|
||||
.terminal-1232074479-r4 { fill: #68a0b3 }
|
||||
.terminal-1232074479-r5 { fill: #00af87 }
|
||||
.terminal-1915255058-r1 { fill: #ff8700 }
|
||||
.terminal-1915255058-r2 { fill: #c5c8c6 }
|
||||
.terminal-1915255058-r3 { fill: #808080 }
|
||||
.terminal-1915255058-r4 { fill: #68a0b3 }
|
||||
.terminal-1915255058-r5 { fill: #00af87 }
|
||||
</style>
|
||||
|
||||
<defs>
|
||||
<clipPath id="terminal-1232074479-clip-terminal">
|
||||
<rect x="0" y="0" width="1463.0" height="926.1999999999999" />
|
||||
<clipPath id="terminal-1915255058-clip-terminal">
|
||||
<rect x="0" y="0" width="1463.0" height="1023.8" />
|
||||
</clipPath>
|
||||
<clipPath id="terminal-1232074479-line-0">
|
||||
<clipPath id="terminal-1915255058-line-0">
|
||||
<rect x="0" y="1.5" width="1464" height="24.65"/>
|
||||
</clipPath>
|
||||
<clipPath id="terminal-1232074479-line-1">
|
||||
<clipPath id="terminal-1915255058-line-1">
|
||||
<rect x="0" y="25.9" width="1464" height="24.65"/>
|
||||
</clipPath>
|
||||
<clipPath id="terminal-1232074479-line-2">
|
||||
<clipPath id="terminal-1915255058-line-2">
|
||||
<rect x="0" y="50.3" width="1464" height="24.65"/>
|
||||
</clipPath>
|
||||
<clipPath id="terminal-1232074479-line-3">
|
||||
<clipPath id="terminal-1915255058-line-3">
|
||||
<rect x="0" y="74.7" width="1464" height="24.65"/>
|
||||
</clipPath>
|
||||
<clipPath id="terminal-1232074479-line-4">
|
||||
<clipPath id="terminal-1915255058-line-4">
|
||||
<rect x="0" y="99.1" width="1464" height="24.65"/>
|
||||
</clipPath>
|
||||
<clipPath id="terminal-1232074479-line-5">
|
||||
<clipPath id="terminal-1915255058-line-5">
|
||||
<rect x="0" y="123.5" width="1464" height="24.65"/>
|
||||
</clipPath>
|
||||
<clipPath id="terminal-1232074479-line-6">
|
||||
<clipPath id="terminal-1915255058-line-6">
|
||||
<rect x="0" y="147.9" width="1464" height="24.65"/>
|
||||
</clipPath>
|
||||
<clipPath id="terminal-1232074479-line-7">
|
||||
<clipPath id="terminal-1915255058-line-7">
|
||||
<rect x="0" y="172.3" width="1464" height="24.65"/>
|
||||
</clipPath>
|
||||
<clipPath id="terminal-1232074479-line-8">
|
||||
<clipPath id="terminal-1915255058-line-8">
|
||||
<rect x="0" y="196.7" width="1464" height="24.65"/>
|
||||
</clipPath>
|
||||
<clipPath id="terminal-1232074479-line-9">
|
||||
<clipPath id="terminal-1915255058-line-9">
|
||||
<rect x="0" y="221.1" width="1464" height="24.65"/>
|
||||
</clipPath>
|
||||
<clipPath id="terminal-1232074479-line-10">
|
||||
<clipPath id="terminal-1915255058-line-10">
|
||||
<rect x="0" y="245.5" width="1464" height="24.65"/>
|
||||
</clipPath>
|
||||
<clipPath id="terminal-1232074479-line-11">
|
||||
<clipPath id="terminal-1915255058-line-11">
|
||||
<rect x="0" y="269.9" width="1464" height="24.65"/>
|
||||
</clipPath>
|
||||
<clipPath id="terminal-1232074479-line-12">
|
||||
<clipPath id="terminal-1915255058-line-12">
|
||||
<rect x="0" y="294.3" width="1464" height="24.65"/>
|
||||
</clipPath>
|
||||
<clipPath id="terminal-1232074479-line-13">
|
||||
<clipPath id="terminal-1915255058-line-13">
|
||||
<rect x="0" y="318.7" width="1464" height="24.65"/>
|
||||
</clipPath>
|
||||
<clipPath id="terminal-1232074479-line-14">
|
||||
<clipPath id="terminal-1915255058-line-14">
|
||||
<rect x="0" y="343.1" width="1464" height="24.65"/>
|
||||
</clipPath>
|
||||
<clipPath id="terminal-1232074479-line-15">
|
||||
<clipPath id="terminal-1915255058-line-15">
|
||||
<rect x="0" y="367.5" width="1464" height="24.65"/>
|
||||
</clipPath>
|
||||
<clipPath id="terminal-1232074479-line-16">
|
||||
<clipPath id="terminal-1915255058-line-16">
|
||||
<rect x="0" y="391.9" width="1464" height="24.65"/>
|
||||
</clipPath>
|
||||
<clipPath id="terminal-1232074479-line-17">
|
||||
<clipPath id="terminal-1915255058-line-17">
|
||||
<rect x="0" y="416.3" width="1464" height="24.65"/>
|
||||
</clipPath>
|
||||
<clipPath id="terminal-1232074479-line-18">
|
||||
<clipPath id="terminal-1915255058-line-18">
|
||||
<rect x="0" y="440.7" width="1464" height="24.65"/>
|
||||
</clipPath>
|
||||
<clipPath id="terminal-1232074479-line-19">
|
||||
<clipPath id="terminal-1915255058-line-19">
|
||||
<rect x="0" y="465.1" width="1464" height="24.65"/>
|
||||
</clipPath>
|
||||
<clipPath id="terminal-1232074479-line-20">
|
||||
<clipPath id="terminal-1915255058-line-20">
|
||||
<rect x="0" y="489.5" width="1464" height="24.65"/>
|
||||
</clipPath>
|
||||
<clipPath id="terminal-1232074479-line-21">
|
||||
<clipPath id="terminal-1915255058-line-21">
|
||||
<rect x="0" y="513.9" width="1464" height="24.65"/>
|
||||
</clipPath>
|
||||
<clipPath id="terminal-1232074479-line-22">
|
||||
<clipPath id="terminal-1915255058-line-22">
|
||||
<rect x="0" y="538.3" width="1464" height="24.65"/>
|
||||
</clipPath>
|
||||
<clipPath id="terminal-1232074479-line-23">
|
||||
<clipPath id="terminal-1915255058-line-23">
|
||||
<rect x="0" y="562.7" width="1464" height="24.65"/>
|
||||
</clipPath>
|
||||
<clipPath id="terminal-1232074479-line-24">
|
||||
<clipPath id="terminal-1915255058-line-24">
|
||||
<rect x="0" y="587.1" width="1464" height="24.65"/>
|
||||
</clipPath>
|
||||
<clipPath id="terminal-1232074479-line-25">
|
||||
<clipPath id="terminal-1915255058-line-25">
|
||||
<rect x="0" y="611.5" width="1464" height="24.65"/>
|
||||
</clipPath>
|
||||
<clipPath id="terminal-1232074479-line-26">
|
||||
<clipPath id="terminal-1915255058-line-26">
|
||||
<rect x="0" y="635.9" width="1464" height="24.65"/>
|
||||
</clipPath>
|
||||
<clipPath id="terminal-1232074479-line-27">
|
||||
<clipPath id="terminal-1915255058-line-27">
|
||||
<rect x="0" y="660.3" width="1464" height="24.65"/>
|
||||
</clipPath>
|
||||
<clipPath id="terminal-1232074479-line-28">
|
||||
<clipPath id="terminal-1915255058-line-28">
|
||||
<rect x="0" y="684.7" width="1464" height="24.65"/>
|
||||
</clipPath>
|
||||
<clipPath id="terminal-1232074479-line-29">
|
||||
<clipPath id="terminal-1915255058-line-29">
|
||||
<rect x="0" y="709.1" width="1464" height="24.65"/>
|
||||
</clipPath>
|
||||
<clipPath id="terminal-1232074479-line-30">
|
||||
<clipPath id="terminal-1915255058-line-30">
|
||||
<rect x="0" y="733.5" width="1464" height="24.65"/>
|
||||
</clipPath>
|
||||
<clipPath id="terminal-1232074479-line-31">
|
||||
<clipPath id="terminal-1915255058-line-31">
|
||||
<rect x="0" y="757.9" width="1464" height="24.65"/>
|
||||
</clipPath>
|
||||
<clipPath id="terminal-1232074479-line-32">
|
||||
<clipPath id="terminal-1915255058-line-32">
|
||||
<rect x="0" y="782.3" width="1464" height="24.65"/>
|
||||
</clipPath>
|
||||
<clipPath id="terminal-1232074479-line-33">
|
||||
<clipPath id="terminal-1915255058-line-33">
|
||||
<rect x="0" y="806.7" width="1464" height="24.65"/>
|
||||
</clipPath>
|
||||
<clipPath id="terminal-1232074479-line-34">
|
||||
<clipPath id="terminal-1915255058-line-34">
|
||||
<rect x="0" y="831.1" width="1464" height="24.65"/>
|
||||
</clipPath>
|
||||
<clipPath id="terminal-1232074479-line-35">
|
||||
<clipPath id="terminal-1915255058-line-35">
|
||||
<rect x="0" y="855.5" width="1464" height="24.65"/>
|
||||
</clipPath>
|
||||
<clipPath id="terminal-1232074479-line-36">
|
||||
<clipPath id="terminal-1915255058-line-36">
|
||||
<rect x="0" y="879.9" width="1464" height="24.65"/>
|
||||
</clipPath>
|
||||
<clipPath id="terminal-1915255058-line-37">
|
||||
<rect x="0" y="904.3" width="1464" height="24.65"/>
|
||||
</clipPath>
|
||||
<clipPath id="terminal-1915255058-line-38">
|
||||
<rect x="0" y="928.7" width="1464" height="24.65"/>
|
||||
</clipPath>
|
||||
<clipPath id="terminal-1915255058-line-39">
|
||||
<rect x="0" y="953.1" width="1464" height="24.65"/>
|
||||
</clipPath>
|
||||
<clipPath id="terminal-1915255058-line-40">
|
||||
<rect x="0" y="977.5" width="1464" height="24.65"/>
|
||||
</clipPath>
|
||||
</defs>
|
||||
|
||||
<rect fill="#292929" stroke="rgba(255,255,255,0.35)" stroke-width="1" x="1" y="1" width="1480" height="975.2" rx="8"/>
|
||||
<rect fill="#292929" stroke="rgba(255,255,255,0.35)" stroke-width="1" x="1" y="1" width="1480" height="1072.8" rx="8"/>
|
||||
<g transform="translate(26,22)">
|
||||
<circle cx="0" cy="0" r="7" fill="#ff5f57"/>
|
||||
<circle cx="22" cy="0" r="7" fill="#febc2e"/>
|
||||
<circle cx="44" cy="0" r="7" fill="#28c840"/>
|
||||
</g>
|
||||
|
||||
<g transform="translate(9, 41)" clip-path="url(#terminal-1232074479-clip-terminal)">
|
||||
<g transform="translate(9, 41)" clip-path="url(#terminal-1915255058-clip-terminal)">
|
||||
|
||||
<g class="terminal-1232074479-matrix">
|
||||
<text class="terminal-1232074479-r1" x="0" y="20" textLength="73.2" clip-path="url(#terminal-1232074479-line-0)">Usage:</text><text class="terminal-1232074479-r3" x="85.4" y="20" textLength="122" clip-path="url(#terminal-1232074479-line-0)">builder.py</text><text class="terminal-1232074479-r2" x="207.4" y="20" textLength="24.4" clip-path="url(#terminal-1232074479-line-0)"> [</text><text class="terminal-1232074479-r4" x="231.8" y="20" textLength="24.4" clip-path="url(#terminal-1232074479-line-0)">-h</text><text class="terminal-1232074479-r2" x="256.2" y="20" textLength="36.6" clip-path="url(#terminal-1232074479-line-0)">] [</text><text class="terminal-1232074479-r4" x="292.8" y="20" textLength="24.4" clip-path="url(#terminal-1232074479-line-0)">-a</text><text class="terminal-1232074479-r5" x="329.4" y="20" textLength="73.2" clip-path="url(#terminal-1232074479-line-0)">AUTHOR</text><text class="terminal-1232074479-r2" x="402.6" y="20" textLength="36.6" clip-path="url(#terminal-1232074479-line-0)">] [</text><text class="terminal-1232074479-r4" x="439.2" y="20" textLength="24.4" clip-path="url(#terminal-1232074479-line-0)">-e</text><text class="terminal-1232074479-r5" x="475.8" y="20" textLength="109.8" clip-path="url(#terminal-1232074479-line-0)">EXTENSION</text><text class="terminal-1232074479-r2" x="585.6" y="20" textLength="36.6" clip-path="url(#terminal-1232074479-line-0)">] [</text><text class="terminal-1232074479-r4" x="622.2" y="20" textLength="24.4" clip-path="url(#terminal-1232074479-line-0)">-l</text><text class="terminal-1232074479-r5" x="658.8" y="20" textLength="85.4" clip-path="url(#terminal-1232074479-line-0)">LICENSE</text><text class="terminal-1232074479-r2" x="744.2" y="20" textLength="36.6" clip-path="url(#terminal-1232074479-line-0)">] [</text><text class="terminal-1232074479-r4" x="780.8" y="20" textLength="24.4" clip-path="url(#terminal-1232074479-line-0)">-m</text><text class="terminal-1232074479-r2" x="805.2" y="20" textLength="36.6" clip-path="url(#terminal-1232074479-line-0)">] [</text><text class="terminal-1232074479-r4" x="841.8" y="20" textLength="24.4" clip-path="url(#terminal-1232074479-line-0)">-n</text><text class="terminal-1232074479-r2" x="866.2" y="20" textLength="24.4" clip-path="url(#terminal-1232074479-line-0)">] </text><text class="terminal-1232074479-r4" x="890.6" y="20" textLength="24.4" clip-path="url(#terminal-1232074479-line-0)">-p</text><text class="terminal-1232074479-r5" x="927.2" y="20" textLength="48.8" clip-path="url(#terminal-1232074479-line-0)">ROOT</text><text class="terminal-1232074479-r4" x="988.2" y="20" textLength="24.4" clip-path="url(#terminal-1232074479-line-0)">-t</text><text class="terminal-1232074479-r5" x="1024.8" y="20" textLength="61" clip-path="url(#terminal-1232074479-line-0)">TITLE</text><text class="terminal-1232074479-r4" x="1098" y="20" textLength="24.4" clip-path="url(#terminal-1232074479-line-0)">-w</text><text class="terminal-1232074479-r5" x="1134.6" y="20" textLength="36.6" clip-path="url(#terminal-1232074479-line-0)">URL</text><text class="terminal-1232074479-r2" x="1464" y="20" textLength="12.2" clip-path="url(#terminal-1232074479-line-0)">
|
||||
</text><text class="terminal-1232074479-r2" x="0" y="44.4" textLength="231.8" clip-path="url(#terminal-1232074479-line-1)">                  [</text><text class="terminal-1232074479-r4" x="231.8" y="44.4" textLength="195.2" clip-path="url(#terminal-1232074479-line-1)">--exclude-folder</text><text class="terminal-1232074479-r5" x="439.2" y="44.4" textLength="73.2" clip-path="url(#terminal-1232074479-line-1)">FOLDER</text><text class="terminal-1232074479-r2" x="512.4" y="44.4" textLength="36.6" clip-path="url(#terminal-1232074479-line-1)">] [</text><text class="terminal-1232074479-r4" x="549" y="44.4" textLength="219.6" clip-path="url(#terminal-1232074479-line-1)">--folderthumbnails</text><text class="terminal-1232074479-r2" x="768.6" y="44.4" textLength="36.6" clip-path="url(#terminal-1232074479-line-1)">] [</text><text class="terminal-1232074479-r4" x="805.2" y="44.4" textLength="244" clip-path="url(#terminal-1232074479-line-1)">--ignore-other-files</text><text class="terminal-1232074479-r2" x="1049.2" y="44.4" textLength="36.6" clip-path="url(#terminal-1232074479-line-1)">] [</text><text class="terminal-1232074479-r4" x="1085.8" y="44.4" textLength="219.6" clip-path="url(#terminal-1232074479-line-1)">--ignore-extension</text><text class="terminal-1232074479-r5" x="1317.6" y="44.4" textLength="109.8" clip-path="url(#terminal-1232074479-line-1)">EXTENSION</text><text class="terminal-1232074479-r2" x="1427.4" y="44.4" textLength="12.2" clip-path="url(#terminal-1232074479-line-1)">]</text><text class="terminal-1232074479-r2" x="1464" y="44.4" textLength="12.2" clip-path="url(#terminal-1232074479-line-1)">
|
||||
</text><text class="terminal-1232074479-r2" x="0" y="68.8" textLength="231.8" clip-path="url(#terminal-1232074479-line-2)">                  [</text><text class="terminal-1232074479-r4" x="231.8" y="68.8" textLength="280.6" clip-path="url(#terminal-1232074479-line-2)">--regenerate-thumbnails</text><text class="terminal-1232074479-r2" x="512.4" y="68.8" textLength="36.6" clip-path="url(#terminal-1232074479-line-2)">] [</text><text class="terminal-1232074479-r4" x="549" y="68.8" textLength="207.4" clip-path="url(#terminal-1232074479-line-2)">--reread-metadata</text><text class="terminal-1232074479-r2" x="756.4" y="68.8" textLength="36.6" clip-path="url(#terminal-1232074479-line-2)">] [</text><text class="terminal-1232074479-r4" x="793" y="68.8" textLength="195.2" clip-path="url(#terminal-1232074479-line-2)">--reread-sidecar</text><text class="terminal-1232074479-r2" x="988.2" y="68.8" textLength="36.6" clip-path="url(#terminal-1232074479-line-2)">] [</text><text class="terminal-1232074479-r4" x="1024.8" y="68.8" textLength="170.8" clip-path="url(#terminal-1232074479-line-2)">--reverse-sort</text><text class="terminal-1232074479-r2" x="1195.6" y="68.8" textLength="12.2" clip-path="url(#terminal-1232074479-line-2)">]</text><text class="terminal-1232074479-r2" x="1464" y="68.8" textLength="12.2" clip-path="url(#terminal-1232074479-line-2)">
|
||||
</text><text class="terminal-1232074479-r2" x="0" y="93.2" textLength="231.8" clip-path="url(#terminal-1232074479-line-3)">                  [</text><text class="terminal-1232074479-r4" x="231.8" y="93.2" textLength="146.4" clip-path="url(#terminal-1232074479-line-3)">--theme-path</text><text class="terminal-1232074479-r5" x="390.4" y="93.2" textLength="48.8" clip-path="url(#terminal-1232074479-line-3)">PATH</text><text class="terminal-1232074479-r2" x="439.2" y="93.2" textLength="36.6" clip-path="url(#terminal-1232074479-line-3)">] [</text><text class="terminal-1232074479-r4" x="475.8" y="93.2" textLength="231.8" clip-path="url(#terminal-1232074479-line-3)">--use-fancy-folders</text><text class="terminal-1232074479-r2" x="707.6" y="93.2" textLength="36.6" clip-path="url(#terminal-1232074479-line-3)">] [</text><text class="terminal-1232074479-r4" x="744.2" y="93.2" textLength="109.8" clip-path="url(#terminal-1232074479-line-3)">--version</text><text class="terminal-1232074479-r2" x="854" y="93.2" textLength="12.2" clip-path="url(#terminal-1232074479-line-3)">]</text><text class="terminal-1232074479-r2" x="1464" y="93.2" textLength="12.2" clip-path="url(#terminal-1232074479-line-3)">
|
||||
</text><text class="terminal-1232074479-r2" x="1464" y="117.6" textLength="12.2" clip-path="url(#terminal-1232074479-line-4)">
|
||||
</text><text class="terminal-1232074479-r2" x="0" y="142" textLength="658.8" clip-path="url(#terminal-1232074479-line-5)">generate HTML files for a static image hosting website</text><text class="terminal-1232074479-r2" x="1464" y="142" textLength="12.2" clip-path="url(#terminal-1232074479-line-5)">
|
||||
</text><text class="terminal-1232074479-r2" x="1464" y="166.4" textLength="12.2" clip-path="url(#terminal-1232074479-line-6)">
|
||||
</text><text class="terminal-1232074479-r1" x="0" y="190.8" textLength="97.6" clip-path="url(#terminal-1232074479-line-7)">Options:</text><text class="terminal-1232074479-r2" x="1464" y="190.8" textLength="12.2" clip-path="url(#terminal-1232074479-line-7)">
|
||||
</text><text class="terminal-1232074479-r4" x="24.4" y="215.2" textLength="24.4" clip-path="url(#terminal-1232074479-line-8)">-h</text><text class="terminal-1232074479-r2" x="48.8" y="215.2" textLength="24.4" clip-path="url(#terminal-1232074479-line-8)">, </text><text class="terminal-1232074479-r4" x="73.2" y="215.2" textLength="73.2" clip-path="url(#terminal-1232074479-line-8)">--help</text><text class="terminal-1232074479-r2" x="292.8" y="215.2" textLength="378.2" clip-path="url(#terminal-1232074479-line-8)">show this help message and exit</text><text class="terminal-1232074479-r2" x="1464" y="215.2" textLength="12.2" clip-path="url(#terminal-1232074479-line-8)">
|
||||
</text><text class="terminal-1232074479-r4" x="24.4" y="239.6" textLength="24.4" clip-path="url(#terminal-1232074479-line-9)">-a</text><text class="terminal-1232074479-r2" x="48.8" y="239.6" textLength="24.4" clip-path="url(#terminal-1232074479-line-9)">, </text><text class="terminal-1232074479-r4" x="73.2" y="239.6" textLength="158.6" clip-path="url(#terminal-1232074479-line-9)">--author-name</text><text class="terminal-1232074479-r5" x="244" y="239.6" textLength="73.2" clip-path="url(#terminal-1232074479-line-9)">AUTHOR</text><text class="terminal-1232074479-r2" x="1464" y="239.6" textLength="12.2" clip-path="url(#terminal-1232074479-line-9)">
|
||||
</text><text class="terminal-1232074479-r2" x="292.8" y="264" textLength="390.4" clip-path="url(#terminal-1232074479-line-10)">name of the author of the images</text><text class="terminal-1232074479-r2" x="1464" y="264" textLength="12.2" clip-path="url(#terminal-1232074479-line-10)">
|
||||
</text><text class="terminal-1232074479-r4" x="24.4" y="288.4" textLength="24.4" clip-path="url(#terminal-1232074479-line-11)">-e</text><text class="terminal-1232074479-r2" x="48.8" y="288.4" textLength="24.4" clip-path="url(#terminal-1232074479-line-11)">, </text><text class="terminal-1232074479-r4" x="73.2" y="288.4" textLength="207.4" clip-path="url(#terminal-1232074479-line-11)">--file-extensions</text><text class="terminal-1232074479-r5" x="292.8" y="288.4" textLength="109.8" clip-path="url(#terminal-1232074479-line-11)">EXTENSION</text><text class="terminal-1232074479-r2" x="1464" y="288.4" textLength="12.2" clip-path="url(#terminal-1232074479-line-11)">
|
||||
</text><text class="terminal-1232074479-r2" x="292.8" y="312.8" textLength="732" clip-path="url(#terminal-1232074479-line-12)">file extensions to include (can be specified multiple times)</text><text class="terminal-1232074479-r2" x="1464" y="312.8" textLength="12.2" clip-path="url(#terminal-1232074479-line-12)">
|
||||
</text><text class="terminal-1232074479-r4" x="24.4" y="337.2" textLength="24.4" clip-path="url(#terminal-1232074479-line-13)">-l</text><text class="terminal-1232074479-r2" x="48.8" y="337.2" textLength="24.4" clip-path="url(#terminal-1232074479-line-13)">, </text><text class="terminal-1232074479-r4" x="73.2" y="337.2" textLength="170.8" clip-path="url(#terminal-1232074479-line-13)">--license-type</text><text class="terminal-1232074479-r5" x="256.2" y="337.2" textLength="85.4" clip-path="url(#terminal-1232074479-line-13)">LICENSE</text><text class="terminal-1232074479-r2" x="1464" y="337.2" textLength="12.2" clip-path="url(#terminal-1232074479-line-13)">
|
||||
</text><text class="terminal-1232074479-r2" x="292.8" y="361.6" textLength="475.8" clip-path="url(#terminal-1232074479-line-14)">specify the license type for the images</text><text class="terminal-1232074479-r2" x="1464" y="361.6" textLength="12.2" clip-path="url(#terminal-1232074479-line-14)">
|
||||
</text><text class="terminal-1232074479-r4" x="24.4" y="386" textLength="24.4" clip-path="url(#terminal-1232074479-line-15)">-m</text><text class="terminal-1232074479-r2" x="48.8" y="386" textLength="24.4" clip-path="url(#terminal-1232074479-line-15)">, </text><text class="terminal-1232074479-r4" x="73.2" y="386" textLength="170.8" clip-path="url(#terminal-1232074479-line-15)">--web-manifest</text><text class="terminal-1232074479-r2" x="292.8" y="386" textLength="341.6" clip-path="url(#terminal-1232074479-line-15)">generate a web manifest file</text><text class="terminal-1232074479-r2" x="1464" y="386" textLength="12.2" clip-path="url(#terminal-1232074479-line-15)">
|
||||
</text><text class="terminal-1232074479-r4" x="24.4" y="410.4" textLength="24.4" clip-path="url(#terminal-1232074479-line-16)">-n</text><text class="terminal-1232074479-r2" x="48.8" y="410.4" textLength="24.4" clip-path="url(#terminal-1232074479-line-16)">, </text><text class="terminal-1232074479-r4" x="73.2" y="410.4" textLength="268.4" clip-path="url(#terminal-1232074479-line-16)">--non-interactive-mode</text><text class="terminal-1232074479-r2" x="1464" y="410.4" textLength="12.2" clip-path="url(#terminal-1232074479-line-16)">
|
||||
</text><text class="terminal-1232074479-r2" x="292.8" y="434.8" textLength="634.4" clip-path="url(#terminal-1232074479-line-17)">run in non-interactive mode, disabling progress bars</text><text class="terminal-1232074479-r2" x="1464" y="434.8" textLength="12.2" clip-path="url(#terminal-1232074479-line-17)">
|
||||
</text><text class="terminal-1232074479-r4" x="24.4" y="459.2" textLength="24.4" clip-path="url(#terminal-1232074479-line-18)">-p</text><text class="terminal-1232074479-r2" x="48.8" y="459.2" textLength="24.4" clip-path="url(#terminal-1232074479-line-18)">, </text><text class="terminal-1232074479-r4" x="73.2" y="459.2" textLength="195.2" clip-path="url(#terminal-1232074479-line-18)">--root-directory</text><text class="terminal-1232074479-r5" x="280.6" y="459.2" textLength="48.8" clip-path="url(#terminal-1232074479-line-18)">ROOT</text><text class="terminal-1232074479-r2" x="1464" y="459.2" textLength="12.2" clip-path="url(#terminal-1232074479-line-18)">
|
||||
</text><text class="terminal-1232074479-r2" x="292.8" y="483.6" textLength="439.2" clip-path="url(#terminal-1232074479-line-19)">root directory containing the images</text><text class="terminal-1232074479-r2" x="1464" y="483.6" textLength="12.2" clip-path="url(#terminal-1232074479-line-19)">
|
||||
</text><text class="terminal-1232074479-r4" x="24.4" y="508" textLength="24.4" clip-path="url(#terminal-1232074479-line-20)">-t</text><text class="terminal-1232074479-r2" x="48.8" y="508" textLength="24.4" clip-path="url(#terminal-1232074479-line-20)">, </text><text class="terminal-1232074479-r4" x="73.2" y="508" textLength="146.4" clip-path="url(#terminal-1232074479-line-20)">--site-title</text><text class="terminal-1232074479-r5" x="231.8" y="508" textLength="61" clip-path="url(#terminal-1232074479-line-20)">TITLE</text><text class="terminal-1232074479-r2" x="1464" y="508" textLength="12.2" clip-path="url(#terminal-1232074479-line-20)">
|
||||
</text><text class="terminal-1232074479-r2" x="292.8" y="532.4" textLength="378.2" clip-path="url(#terminal-1232074479-line-21)">title of the image hosting site</text><text class="terminal-1232074479-r2" x="1464" y="532.4" textLength="12.2" clip-path="url(#terminal-1232074479-line-21)">
|
||||
</text><text class="terminal-1232074479-r4" x="24.4" y="556.8" textLength="24.4" clip-path="url(#terminal-1232074479-line-22)">-w</text><text class="terminal-1232074479-r2" x="48.8" y="556.8" textLength="24.4" clip-path="url(#terminal-1232074479-line-22)">, </text><text class="terminal-1232074479-r4" x="73.2" y="556.8" textLength="170.8" clip-path="url(#terminal-1232074479-line-22)">--web-root-url</text><text class="terminal-1232074479-r5" x="256.2" y="556.8" textLength="36.6" clip-path="url(#terminal-1232074479-line-22)">URL</text><text class="terminal-1232074479-r2" x="1464" y="556.8" textLength="12.2" clip-path="url(#terminal-1232074479-line-22)">
|
||||
</text><text class="terminal-1232074479-r2" x="292.8" y="581.2" textLength="622.2" clip-path="url(#terminal-1232074479-line-23)">base URL of the web root for the image hosting site</text><text class="terminal-1232074479-r2" x="1464" y="581.2" textLength="12.2" clip-path="url(#terminal-1232074479-line-23)">
|
||||
</text><text class="terminal-1232074479-r4" x="24.4" y="605.6" textLength="195.2" clip-path="url(#terminal-1232074479-line-24)">--exclude-folder</text><text class="terminal-1232074479-r5" x="231.8" y="605.6" textLength="73.2" clip-path="url(#terminal-1232074479-line-24)">FOLDER</text><text class="terminal-1232074479-r2" x="1464" y="605.6" textLength="12.2" clip-path="url(#terminal-1232074479-line-24)">
|
||||
</text><text class="terminal-1232074479-r2" x="292.8" y="630" textLength="1037" clip-path="url(#terminal-1232074479-line-25)">folders to exclude from processing, globs supported (can be specified multiple times)</text><text class="terminal-1232074479-r2" x="1464" y="630" textLength="12.2" clip-path="url(#terminal-1232074479-line-25)">
|
||||
</text><text class="terminal-1232074479-r4" x="24.4" y="654.4" textLength="219.6" clip-path="url(#terminal-1232074479-line-26)">--folderthumbnails</text><text class="terminal-1232074479-r2" x="292.8" y="654.4" textLength="817.4" clip-path="url(#terminal-1232074479-line-26)">generate subfolder thumbnails (first image in folder will be shown)</text><text class="terminal-1232074479-r2" x="1464" y="654.4" textLength="12.2" clip-path="url(#terminal-1232074479-line-26)">
|
||||
</text><text class="terminal-1232074479-r4" x="24.4" y="678.8" textLength="244" clip-path="url(#terminal-1232074479-line-27)">--ignore-other-files</text><text class="terminal-1232074479-r2" x="292.8" y="678.8" textLength="671" clip-path="url(#terminal-1232074479-line-27)">ignore files that do not match the specified extensions</text><text class="terminal-1232074479-r2" x="1464" y="678.8" textLength="12.2" clip-path="url(#terminal-1232074479-line-27)">
|
||||
</text><text class="terminal-1232074479-r4" x="24.4" y="703.2" textLength="219.6" clip-path="url(#terminal-1232074479-line-28)">--ignore-extension</text><text class="terminal-1232074479-r5" x="256.2" y="703.2" textLength="109.8" clip-path="url(#terminal-1232074479-line-28)">EXTENSION</text><text class="terminal-1232074479-r2" x="1464" y="703.2" textLength="12.2" clip-path="url(#terminal-1232074479-line-28)">
|
||||
</text><text class="terminal-1232074479-r2" x="292.8" y="727.6" textLength="719.8" clip-path="url(#terminal-1232074479-line-29)">file extensions to ignore (can be specified multiple times)</text><text class="terminal-1232074479-r2" x="1464" y="727.6" textLength="12.2" clip-path="url(#terminal-1232074479-line-29)">
|
||||
</text><text class="terminal-1232074479-r4" x="24.4" y="752" textLength="280.6" clip-path="url(#terminal-1232074479-line-30)">--regenerate-thumbnails</text><text class="terminal-1232074479-r2" x="1464" y="752" textLength="12.2" clip-path="url(#terminal-1232074479-line-30)">
|
||||
</text><text class="terminal-1232074479-r2" x="292.8" y="776.4" textLength="585.6" clip-path="url(#terminal-1232074479-line-31)">regenerate thumbnails even if they already exist</text><text class="terminal-1232074479-r2" x="1464" y="776.4" textLength="12.2" clip-path="url(#terminal-1232074479-line-31)">
|
||||
</text><text class="terminal-1232074479-r4" x="24.4" y="800.8" textLength="207.4" clip-path="url(#terminal-1232074479-line-32)">--reread-metadata</text><text class="terminal-1232074479-r2" x="292.8" y="800.8" textLength="256.2" clip-path="url(#terminal-1232074479-line-32)">reread image metadata</text><text class="terminal-1232074479-r2" x="1464" y="800.8" textLength="12.2" clip-path="url(#terminal-1232074479-line-32)">
|
||||
</text><text class="terminal-1232074479-r4" x="24.4" y="825.2" textLength="195.2" clip-path="url(#terminal-1232074479-line-33)">--reread-sidecar</text><text class="terminal-1232074479-r2" x="292.8" y="825.2" textLength="244" clip-path="url(#terminal-1232074479-line-33)">reread sidecar files</text><text class="terminal-1232074479-r2" x="1464" y="825.2" textLength="12.2" clip-path="url(#terminal-1232074479-line-33)">
|
||||
</text><text class="terminal-1232074479-r4" x="24.4" y="849.6" textLength="170.8" clip-path="url(#terminal-1232074479-line-34)">--reverse-sort</text><text class="terminal-1232074479-r2" x="292.8" y="849.6" textLength="341.6" clip-path="url(#terminal-1232074479-line-34)">sort images in reverse order</text><text class="terminal-1232074479-r2" x="1464" y="849.6" textLength="12.2" clip-path="url(#terminal-1232074479-line-34)">
|
||||
</text><text class="terminal-1232074479-r4" x="24.4" y="874" textLength="146.4" clip-path="url(#terminal-1232074479-line-35)">--theme-path</text><text class="terminal-1232074479-r5" x="183" y="874" textLength="48.8" clip-path="url(#terminal-1232074479-line-35)">PATH</text><text class="terminal-1232074479-r2" x="292.8" y="874" textLength="317.2" clip-path="url(#terminal-1232074479-line-35)">path to the CSS theme file</text><text class="terminal-1232074479-r2" x="1464" y="874" textLength="12.2" clip-path="url(#terminal-1232074479-line-35)">
|
||||
</text><text class="terminal-1232074479-r4" x="24.4" y="898.4" textLength="231.8" clip-path="url(#terminal-1232074479-line-36)">--use-fancy-folders</text><text class="terminal-1232074479-r2" x="292.8" y="898.4" textLength="878.4" clip-path="url(#terminal-1232074479-line-36)">enable fancy folder view instead of the default Apache directory listing</text><text class="terminal-1232074479-r2" x="1464" y="898.4" textLength="12.2" clip-path="url(#terminal-1232074479-line-36)">
|
||||
</text><text class="terminal-1232074479-r4" x="24.4" y="922.8" textLength="109.8" clip-path="url(#terminal-1232074479-line-37)">--version</text><text class="terminal-1232074479-r2" x="292.8" y="922.8" textLength="463.6" clip-path="url(#terminal-1232074479-line-37)">show program's version number and exit</text><text class="terminal-1232074479-r2" x="1464" y="922.8" textLength="12.2" clip-path="url(#terminal-1232074479-line-37)">
|
||||
<g class="terminal-1915255058-matrix">
|
||||
<text class="terminal-1915255058-r1" x="0" y="20" textLength="73.2" clip-path="url(#terminal-1915255058-line-0)">Usage:</text><text class="terminal-1915255058-r3" x="85.4" y="20" textLength="122" clip-path="url(#terminal-1915255058-line-0)">builder.py</text><text class="terminal-1915255058-r2" x="207.4" y="20" textLength="24.4" clip-path="url(#terminal-1915255058-line-0)"> [</text><text class="terminal-1915255058-r4" x="231.8" y="20" textLength="24.4" clip-path="url(#terminal-1915255058-line-0)">-h</text><text class="terminal-1915255058-r2" x="256.2" y="20" textLength="36.6" clip-path="url(#terminal-1915255058-line-0)">] [</text><text class="terminal-1915255058-r4" x="292.8" y="20" textLength="24.4" clip-path="url(#terminal-1915255058-line-0)">-a</text><text class="terminal-1915255058-r5" x="329.4" y="20" textLength="73.2" clip-path="url(#terminal-1915255058-line-0)">AUTHOR</text><text class="terminal-1915255058-r2" x="402.6" y="20" textLength="36.6" clip-path="url(#terminal-1915255058-line-0)">] [</text><text class="terminal-1915255058-r4" x="439.2" y="20" textLength="24.4" clip-path="url(#terminal-1915255058-line-0)">-e</text><text class="terminal-1915255058-r5" x="475.8" y="20" textLength="109.8" clip-path="url(#terminal-1915255058-line-0)">EXTENSION</text><text class="terminal-1915255058-r2" x="585.6" y="20" textLength="36.6" clip-path="url(#terminal-1915255058-line-0)">] [</text><text class="terminal-1915255058-r4" x="622.2" y="20" textLength="24.4" clip-path="url(#terminal-1915255058-line-0)">-l</text><text class="terminal-1915255058-r5" x="658.8" y="20" textLength="85.4" clip-path="url(#terminal-1915255058-line-0)">LICENSE</text><text class="terminal-1915255058-r2" x="744.2" y="20" textLength="36.6" clip-path="url(#terminal-1915255058-line-0)">] [</text><text class="terminal-1915255058-r4" x="780.8" y="20" textLength="24.4" clip-path="url(#terminal-1915255058-line-0)">-m</text><text class="terminal-1915255058-r2" x="805.2" y="20" textLength="36.6" clip-path="url(#terminal-1915255058-line-0)">] [</text><text class="terminal-1915255058-r4" x="841.8" y="20" textLength="24.4" clip-path="url(#terminal-1915255058-line-0)">-n</text><text class="terminal-1915255058-r2" x="866.2" y="20" textLength="24.4" clip-path="url(#terminal-1915255058-line-0)">] </text><text class="terminal-1915255058-r4" x="890.6" y="20" textLength="24.4" clip-path="url(#terminal-1915255058-line-0)">-p</text><text class="terminal-1915255058-r5" x="927.2" y="20" textLength="48.8" clip-path="url(#terminal-1915255058-line-0)">ROOT</text><text class="terminal-1915255058-r4" x="988.2" y="20" textLength="24.4" clip-path="url(#terminal-1915255058-line-0)">-t</text><text class="terminal-1915255058-r5" x="1024.8" y="20" textLength="61" clip-path="url(#terminal-1915255058-line-0)">TITLE</text><text class="terminal-1915255058-r4" x="1098" y="20" textLength="24.4" clip-path="url(#terminal-1915255058-line-0)">-w</text><text class="terminal-1915255058-r5" x="1134.6" y="20" textLength="36.6" clip-path="url(#terminal-1915255058-line-0)">URL</text><text class="terminal-1915255058-r2" x="1171.2" y="20" textLength="24.4" clip-path="url(#terminal-1915255058-line-0)"> [</text><text class="terminal-1915255058-r4" x="1195.6" y="20" textLength="24.4" clip-path="url(#terminal-1915255058-line-0)">-c</text><text class="terminal-1915255058-r5" x="1232.2" y="20" textLength="134.2" clip-path="url(#terminal-1915255058-line-0)">CONFIG_FILE</text><text class="terminal-1915255058-r2" x="1366.4" y="20" textLength="12.2" clip-path="url(#terminal-1915255058-line-0)">]</text><text class="terminal-1915255058-r2" x="1464" y="20" textLength="12.2" clip-path="url(#terminal-1915255058-line-0)">
|
||||
</text><text class="terminal-1915255058-r2" x="0" y="44.4" textLength="231.8" clip-path="url(#terminal-1915255058-line-1)">                  [</text><text class="terminal-1915255058-r4" x="231.8" y="44.4" textLength="195.2" clip-path="url(#terminal-1915255058-line-1)">--exclude-folder</text><text class="terminal-1915255058-r5" x="439.2" y="44.4" textLength="73.2" clip-path="url(#terminal-1915255058-line-1)">FOLDER</text><text class="terminal-1915255058-r2" x="512.4" y="44.4" textLength="36.6" clip-path="url(#terminal-1915255058-line-1)">] [</text><text class="terminal-1915255058-r4" x="549" y="44.4" textLength="219.6" clip-path="url(#terminal-1915255058-line-1)">--folderthumbnails</text><text class="terminal-1915255058-r2" x="768.6" y="44.4" textLength="36.6" clip-path="url(#terminal-1915255058-line-1)">] [</text><text class="terminal-1915255058-r4" x="805.2" y="44.4" textLength="244" clip-path="url(#terminal-1915255058-line-1)">--ignore-other-files</text><text class="terminal-1915255058-r2" x="1049.2" y="44.4" textLength="36.6" clip-path="url(#terminal-1915255058-line-1)">] [</text><text class="terminal-1915255058-r4" x="1085.8" y="44.4" textLength="219.6" clip-path="url(#terminal-1915255058-line-1)">--ignore-extension</text><text class="terminal-1915255058-r5" x="1317.6" y="44.4" textLength="109.8" clip-path="url(#terminal-1915255058-line-1)">EXTENSION</text><text class="terminal-1915255058-r2" x="1427.4" y="44.4" textLength="12.2" clip-path="url(#terminal-1915255058-line-1)">]</text><text class="terminal-1915255058-r2" x="1464" y="44.4" textLength="12.2" clip-path="url(#terminal-1915255058-line-1)">
|
||||
</text><text class="terminal-1915255058-r2" x="0" y="68.8" textLength="231.8" clip-path="url(#terminal-1915255058-line-2)">                  [</text><text class="terminal-1915255058-r4" x="231.8" y="68.8" textLength="280.6" clip-path="url(#terminal-1915255058-line-2)">--regenerate-thumbnails</text><text class="terminal-1915255058-r2" x="512.4" y="68.8" textLength="36.6" clip-path="url(#terminal-1915255058-line-2)">] [</text><text class="terminal-1915255058-r4" x="549" y="68.8" textLength="207.4" clip-path="url(#terminal-1915255058-line-2)">--reread-metadata</text><text class="terminal-1915255058-r2" x="756.4" y="68.8" textLength="36.6" clip-path="url(#terminal-1915255058-line-2)">] [</text><text class="terminal-1915255058-r4" x="793" y="68.8" textLength="195.2" clip-path="url(#terminal-1915255058-line-2)">--reread-sidecar</text><text class="terminal-1915255058-r2" x="988.2" y="68.8" textLength="36.6" clip-path="url(#terminal-1915255058-line-2)">] [</text><text class="terminal-1915255058-r4" x="1024.8" y="68.8" textLength="170.8" clip-path="url(#terminal-1915255058-line-2)">--reverse-sort</text><text class="terminal-1915255058-r2" x="1195.6" y="68.8" textLength="12.2" clip-path="url(#terminal-1915255058-line-2)">]</text><text class="terminal-1915255058-r2" x="1464" y="68.8" textLength="12.2" clip-path="url(#terminal-1915255058-line-2)">
|
||||
</text><text class="terminal-1915255058-r2" x="0" y="93.2" textLength="231.8" clip-path="url(#terminal-1915255058-line-3)">                  [</text><text class="terminal-1915255058-r4" x="231.8" y="93.2" textLength="146.4" clip-path="url(#terminal-1915255058-line-3)">--theme-path</text><text class="terminal-1915255058-r5" x="390.4" y="93.2" textLength="48.8" clip-path="url(#terminal-1915255058-line-3)">PATH</text><text class="terminal-1915255058-r2" x="439.2" y="93.2" textLength="36.6" clip-path="url(#terminal-1915255058-line-3)">] [</text><text class="terminal-1915255058-r4" x="475.8" y="93.2" textLength="231.8" clip-path="url(#terminal-1915255058-line-3)">--use-fancy-folders</text><text class="terminal-1915255058-r2" x="707.6" y="93.2" textLength="36.6" clip-path="url(#terminal-1915255058-line-3)">] [</text><text class="terminal-1915255058-r4" x="744.2" y="93.2" textLength="109.8" clip-path="url(#terminal-1915255058-line-3)">--version</text><text class="terminal-1915255058-r2" x="854" y="93.2" textLength="36.6" clip-path="url(#terminal-1915255058-line-3)">] [</text><text class="terminal-1915255058-r4" x="890.6" y="93.2" textLength="170.8" clip-path="url(#terminal-1915255058-line-3)">--write-config</text><text class="terminal-1915255058-r5" x="1073.6" y="93.2" textLength="134.2" clip-path="url(#terminal-1915255058-line-3)">CONFIG_FILE</text><text class="terminal-1915255058-r2" x="1207.8" y="93.2" textLength="12.2" clip-path="url(#terminal-1915255058-line-3)">]</text><text class="terminal-1915255058-r2" x="1464" y="93.2" textLength="12.2" clip-path="url(#terminal-1915255058-line-3)">
|
||||
</text><text class="terminal-1915255058-r2" x="1464" y="117.6" textLength="12.2" clip-path="url(#terminal-1915255058-line-4)">
|
||||
</text><text class="terminal-1915255058-r2" x="0" y="142" textLength="658.8" clip-path="url(#terminal-1915255058-line-5)">generate HTML files for a static image hosting website</text><text class="terminal-1915255058-r2" x="1464" y="142" textLength="12.2" clip-path="url(#terminal-1915255058-line-5)">
|
||||
</text><text class="terminal-1915255058-r2" x="1464" y="166.4" textLength="12.2" clip-path="url(#terminal-1915255058-line-6)">
|
||||
</text><text class="terminal-1915255058-r1" x="0" y="190.8" textLength="97.6" clip-path="url(#terminal-1915255058-line-7)">Options:</text><text class="terminal-1915255058-r2" x="1464" y="190.8" textLength="12.2" clip-path="url(#terminal-1915255058-line-7)">
|
||||
</text><text class="terminal-1915255058-r4" x="24.4" y="215.2" textLength="24.4" clip-path="url(#terminal-1915255058-line-8)">-h</text><text class="terminal-1915255058-r2" x="48.8" y="215.2" textLength="24.4" clip-path="url(#terminal-1915255058-line-8)">, </text><text class="terminal-1915255058-r4" x="73.2" y="215.2" textLength="73.2" clip-path="url(#terminal-1915255058-line-8)">--help</text><text class="terminal-1915255058-r2" x="292.8" y="215.2" textLength="378.2" clip-path="url(#terminal-1915255058-line-8)">show this help message and exit</text><text class="terminal-1915255058-r2" x="1464" y="215.2" textLength="12.2" clip-path="url(#terminal-1915255058-line-8)">
|
||||
</text><text class="terminal-1915255058-r4" x="24.4" y="239.6" textLength="24.4" clip-path="url(#terminal-1915255058-line-9)">-a</text><text class="terminal-1915255058-r2" x="48.8" y="239.6" textLength="24.4" clip-path="url(#terminal-1915255058-line-9)">, </text><text class="terminal-1915255058-r4" x="73.2" y="239.6" textLength="158.6" clip-path="url(#terminal-1915255058-line-9)">--author-name</text><text class="terminal-1915255058-r5" x="244" y="239.6" textLength="73.2" clip-path="url(#terminal-1915255058-line-9)">AUTHOR</text><text class="terminal-1915255058-r2" x="1464" y="239.6" textLength="12.2" clip-path="url(#terminal-1915255058-line-9)">
|
||||
</text><text class="terminal-1915255058-r2" x="292.8" y="264" textLength="390.4" clip-path="url(#terminal-1915255058-line-10)">name of the author of the images</text><text class="terminal-1915255058-r2" x="1464" y="264" textLength="12.2" clip-path="url(#terminal-1915255058-line-10)">
|
||||
</text><text class="terminal-1915255058-r4" x="24.4" y="288.4" textLength="24.4" clip-path="url(#terminal-1915255058-line-11)">-e</text><text class="terminal-1915255058-r2" x="48.8" y="288.4" textLength="24.4" clip-path="url(#terminal-1915255058-line-11)">, </text><text class="terminal-1915255058-r4" x="73.2" y="288.4" textLength="207.4" clip-path="url(#terminal-1915255058-line-11)">--file-extensions</text><text class="terminal-1915255058-r5" x="292.8" y="288.4" textLength="109.8" clip-path="url(#terminal-1915255058-line-11)">EXTENSION</text><text class="terminal-1915255058-r2" x="1464" y="288.4" textLength="12.2" clip-path="url(#terminal-1915255058-line-11)">
|
||||
</text><text class="terminal-1915255058-r2" x="292.8" y="312.8" textLength="732" clip-path="url(#terminal-1915255058-line-12)">file extensions to include (can be specified multiple times)</text><text class="terminal-1915255058-r2" x="1464" y="312.8" textLength="12.2" clip-path="url(#terminal-1915255058-line-12)">
|
||||
</text><text class="terminal-1915255058-r4" x="24.4" y="337.2" textLength="24.4" clip-path="url(#terminal-1915255058-line-13)">-l</text><text class="terminal-1915255058-r2" x="48.8" y="337.2" textLength="24.4" clip-path="url(#terminal-1915255058-line-13)">, </text><text class="terminal-1915255058-r4" x="73.2" y="337.2" textLength="170.8" clip-path="url(#terminal-1915255058-line-13)">--license-type</text><text class="terminal-1915255058-r5" x="256.2" y="337.2" textLength="85.4" clip-path="url(#terminal-1915255058-line-13)">LICENSE</text><text class="terminal-1915255058-r2" x="1464" y="337.2" textLength="12.2" clip-path="url(#terminal-1915255058-line-13)">
|
||||
</text><text class="terminal-1915255058-r2" x="292.8" y="361.6" textLength="475.8" clip-path="url(#terminal-1915255058-line-14)">specify the license type for the images</text><text class="terminal-1915255058-r2" x="1464" y="361.6" textLength="12.2" clip-path="url(#terminal-1915255058-line-14)">
|
||||
</text><text class="terminal-1915255058-r4" x="24.4" y="386" textLength="24.4" clip-path="url(#terminal-1915255058-line-15)">-m</text><text class="terminal-1915255058-r2" x="48.8" y="386" textLength="24.4" clip-path="url(#terminal-1915255058-line-15)">, </text><text class="terminal-1915255058-r4" x="73.2" y="386" textLength="170.8" clip-path="url(#terminal-1915255058-line-15)">--web-manifest</text><text class="terminal-1915255058-r2" x="292.8" y="386" textLength="341.6" clip-path="url(#terminal-1915255058-line-15)">generate a web manifest file</text><text class="terminal-1915255058-r2" x="1464" y="386" textLength="12.2" clip-path="url(#terminal-1915255058-line-15)">
|
||||
</text><text class="terminal-1915255058-r4" x="24.4" y="410.4" textLength="24.4" clip-path="url(#terminal-1915255058-line-16)">-n</text><text class="terminal-1915255058-r2" x="48.8" y="410.4" textLength="24.4" clip-path="url(#terminal-1915255058-line-16)">, </text><text class="terminal-1915255058-r4" x="73.2" y="410.4" textLength="268.4" clip-path="url(#terminal-1915255058-line-16)">--non-interactive-mode</text><text class="terminal-1915255058-r2" x="1464" y="410.4" textLength="12.2" clip-path="url(#terminal-1915255058-line-16)">
|
||||
</text><text class="terminal-1915255058-r2" x="292.8" y="434.8" textLength="634.4" clip-path="url(#terminal-1915255058-line-17)">run in non-interactive mode, disabling progress bars</text><text class="terminal-1915255058-r2" x="1464" y="434.8" textLength="12.2" clip-path="url(#terminal-1915255058-line-17)">
|
||||
</text><text class="terminal-1915255058-r4" x="24.4" y="459.2" textLength="24.4" clip-path="url(#terminal-1915255058-line-18)">-p</text><text class="terminal-1915255058-r2" x="48.8" y="459.2" textLength="24.4" clip-path="url(#terminal-1915255058-line-18)">, </text><text class="terminal-1915255058-r4" x="73.2" y="459.2" textLength="195.2" clip-path="url(#terminal-1915255058-line-18)">--root-directory</text><text class="terminal-1915255058-r5" x="280.6" y="459.2" textLength="48.8" clip-path="url(#terminal-1915255058-line-18)">ROOT</text><text class="terminal-1915255058-r2" x="1464" y="459.2" textLength="12.2" clip-path="url(#terminal-1915255058-line-18)">
|
||||
</text><text class="terminal-1915255058-r2" x="292.8" y="483.6" textLength="439.2" clip-path="url(#terminal-1915255058-line-19)">root directory containing the images</text><text class="terminal-1915255058-r2" x="1464" y="483.6" textLength="12.2" clip-path="url(#terminal-1915255058-line-19)">
|
||||
</text><text class="terminal-1915255058-r4" x="24.4" y="508" textLength="24.4" clip-path="url(#terminal-1915255058-line-20)">-t</text><text class="terminal-1915255058-r2" x="48.8" y="508" textLength="24.4" clip-path="url(#terminal-1915255058-line-20)">, </text><text class="terminal-1915255058-r4" x="73.2" y="508" textLength="146.4" clip-path="url(#terminal-1915255058-line-20)">--site-title</text><text class="terminal-1915255058-r5" x="231.8" y="508" textLength="61" clip-path="url(#terminal-1915255058-line-20)">TITLE</text><text class="terminal-1915255058-r2" x="1464" y="508" textLength="12.2" clip-path="url(#terminal-1915255058-line-20)">
|
||||
</text><text class="terminal-1915255058-r2" x="292.8" y="532.4" textLength="378.2" clip-path="url(#terminal-1915255058-line-21)">title of the image hosting site</text><text class="terminal-1915255058-r2" x="1464" y="532.4" textLength="12.2" clip-path="url(#terminal-1915255058-line-21)">
|
||||
</text><text class="terminal-1915255058-r4" x="24.4" y="556.8" textLength="24.4" clip-path="url(#terminal-1915255058-line-22)">-w</text><text class="terminal-1915255058-r2" x="48.8" y="556.8" textLength="24.4" clip-path="url(#terminal-1915255058-line-22)">, </text><text class="terminal-1915255058-r4" x="73.2" y="556.8" textLength="170.8" clip-path="url(#terminal-1915255058-line-22)">--web-root-url</text><text class="terminal-1915255058-r5" x="256.2" y="556.8" textLength="36.6" clip-path="url(#terminal-1915255058-line-22)">URL</text><text class="terminal-1915255058-r2" x="1464" y="556.8" textLength="12.2" clip-path="url(#terminal-1915255058-line-22)">
|
||||
</text><text class="terminal-1915255058-r2" x="292.8" y="581.2" textLength="622.2" clip-path="url(#terminal-1915255058-line-23)">base URL of the web root for the image hosting site</text><text class="terminal-1915255058-r2" x="1464" y="581.2" textLength="12.2" clip-path="url(#terminal-1915255058-line-23)">
|
||||
</text><text class="terminal-1915255058-r4" x="24.4" y="605.6" textLength="24.4" clip-path="url(#terminal-1915255058-line-24)">-c</text><text class="terminal-1915255058-r2" x="48.8" y="605.6" textLength="24.4" clip-path="url(#terminal-1915255058-line-24)">, </text><text class="terminal-1915255058-r4" x="73.2" y="605.6" textLength="158.6" clip-path="url(#terminal-1915255058-line-24)">--config-file</text><text class="terminal-1915255058-r5" x="244" y="605.6" textLength="134.2" clip-path="url(#terminal-1915255058-line-24)">CONFIG_FILE</text><text class="terminal-1915255058-r2" x="1464" y="605.6" textLength="12.2" clip-path="url(#terminal-1915255058-line-24)">
|
||||
</text><text class="terminal-1915255058-r2" x="292.8" y="630" textLength="195.2" clip-path="url(#terminal-1915255058-line-25)">config file path</text><text class="terminal-1915255058-r2" x="1464" y="630" textLength="12.2" clip-path="url(#terminal-1915255058-line-25)">
|
||||
</text><text class="terminal-1915255058-r4" x="24.4" y="654.4" textLength="195.2" clip-path="url(#terminal-1915255058-line-26)">--exclude-folder</text><text class="terminal-1915255058-r5" x="231.8" y="654.4" textLength="73.2" clip-path="url(#terminal-1915255058-line-26)">FOLDER</text><text class="terminal-1915255058-r2" x="1464" y="654.4" textLength="12.2" clip-path="url(#terminal-1915255058-line-26)">
|
||||
</text><text class="terminal-1915255058-r2" x="292.8" y="678.8" textLength="1037" clip-path="url(#terminal-1915255058-line-27)">folders to exclude from processing, globs supported (can be specified multiple times)</text><text class="terminal-1915255058-r2" x="1464" y="678.8" textLength="12.2" clip-path="url(#terminal-1915255058-line-27)">
|
||||
</text><text class="terminal-1915255058-r4" x="24.4" y="703.2" textLength="219.6" clip-path="url(#terminal-1915255058-line-28)">--folderthumbnails</text><text class="terminal-1915255058-r2" x="292.8" y="703.2" textLength="817.4" clip-path="url(#terminal-1915255058-line-28)">generate subfolder thumbnails (first image in folder will be shown)</text><text class="terminal-1915255058-r2" x="1464" y="703.2" textLength="12.2" clip-path="url(#terminal-1915255058-line-28)">
|
||||
</text><text class="terminal-1915255058-r4" x="24.4" y="727.6" textLength="244" clip-path="url(#terminal-1915255058-line-29)">--ignore-other-files</text><text class="terminal-1915255058-r2" x="292.8" y="727.6" textLength="671" clip-path="url(#terminal-1915255058-line-29)">ignore files that do not match the specified extensions</text><text class="terminal-1915255058-r2" x="1464" y="727.6" textLength="12.2" clip-path="url(#terminal-1915255058-line-29)">
|
||||
</text><text class="terminal-1915255058-r4" x="24.4" y="752" textLength="219.6" clip-path="url(#terminal-1915255058-line-30)">--ignore-extension</text><text class="terminal-1915255058-r5" x="256.2" y="752" textLength="109.8" clip-path="url(#terminal-1915255058-line-30)">EXTENSION</text><text class="terminal-1915255058-r2" x="1464" y="752" textLength="12.2" clip-path="url(#terminal-1915255058-line-30)">
|
||||
</text><text class="terminal-1915255058-r2" x="292.8" y="776.4" textLength="719.8" clip-path="url(#terminal-1915255058-line-31)">file extensions to ignore (can be specified multiple times)</text><text class="terminal-1915255058-r2" x="1464" y="776.4" textLength="12.2" clip-path="url(#terminal-1915255058-line-31)">
|
||||
</text><text class="terminal-1915255058-r4" x="24.4" y="800.8" textLength="280.6" clip-path="url(#terminal-1915255058-line-32)">--regenerate-thumbnails</text><text class="terminal-1915255058-r2" x="1464" y="800.8" textLength="12.2" clip-path="url(#terminal-1915255058-line-32)">
|
||||
</text><text class="terminal-1915255058-r2" x="292.8" y="825.2" textLength="585.6" clip-path="url(#terminal-1915255058-line-33)">regenerate thumbnails even if they already exist</text><text class="terminal-1915255058-r2" x="1464" y="825.2" textLength="12.2" clip-path="url(#terminal-1915255058-line-33)">
|
||||
</text><text class="terminal-1915255058-r4" x="24.4" y="849.6" textLength="207.4" clip-path="url(#terminal-1915255058-line-34)">--reread-metadata</text><text class="terminal-1915255058-r2" x="292.8" y="849.6" textLength="256.2" clip-path="url(#terminal-1915255058-line-34)">reread image metadata</text><text class="terminal-1915255058-r2" x="1464" y="849.6" textLength="12.2" clip-path="url(#terminal-1915255058-line-34)">
|
||||
</text><text class="terminal-1915255058-r4" x="24.4" y="874" textLength="195.2" clip-path="url(#terminal-1915255058-line-35)">--reread-sidecar</text><text class="terminal-1915255058-r2" x="292.8" y="874" textLength="244" clip-path="url(#terminal-1915255058-line-35)">reread sidecar files</text><text class="terminal-1915255058-r2" x="1464" y="874" textLength="12.2" clip-path="url(#terminal-1915255058-line-35)">
|
||||
</text><text class="terminal-1915255058-r4" x="24.4" y="898.4" textLength="170.8" clip-path="url(#terminal-1915255058-line-36)">--reverse-sort</text><text class="terminal-1915255058-r2" x="292.8" y="898.4" textLength="341.6" clip-path="url(#terminal-1915255058-line-36)">sort images in reverse order</text><text class="terminal-1915255058-r2" x="1464" y="898.4" textLength="12.2" clip-path="url(#terminal-1915255058-line-36)">
|
||||
</text><text class="terminal-1915255058-r4" x="24.4" y="922.8" textLength="146.4" clip-path="url(#terminal-1915255058-line-37)">--theme-path</text><text class="terminal-1915255058-r5" x="183" y="922.8" textLength="48.8" clip-path="url(#terminal-1915255058-line-37)">PATH</text><text class="terminal-1915255058-r2" x="292.8" y="922.8" textLength="317.2" clip-path="url(#terminal-1915255058-line-37)">path to the CSS theme file</text><text class="terminal-1915255058-r2" x="1464" y="922.8" textLength="12.2" clip-path="url(#terminal-1915255058-line-37)">
|
||||
</text><text class="terminal-1915255058-r4" x="24.4" y="947.2" textLength="231.8" clip-path="url(#terminal-1915255058-line-38)">--use-fancy-folders</text><text class="terminal-1915255058-r2" x="292.8" y="947.2" textLength="878.4" clip-path="url(#terminal-1915255058-line-38)">enable fancy folder view instead of the default Apache directory listing</text><text class="terminal-1915255058-r2" x="1464" y="947.2" textLength="12.2" clip-path="url(#terminal-1915255058-line-38)">
|
||||
</text><text class="terminal-1915255058-r4" x="24.4" y="971.6" textLength="109.8" clip-path="url(#terminal-1915255058-line-39)">--version</text><text class="terminal-1915255058-r2" x="292.8" y="971.6" textLength="463.6" clip-path="url(#terminal-1915255058-line-39)">show program's version number and exit</text><text class="terminal-1915255058-r2" x="1464" y="971.6" textLength="12.2" clip-path="url(#terminal-1915255058-line-39)">
|
||||
</text><text class="terminal-1915255058-r4" x="24.4" y="996" textLength="170.8" clip-path="url(#terminal-1915255058-line-40)">--write-config</text><text class="terminal-1915255058-r5" x="207.4" y="996" textLength="134.2" clip-path="url(#terminal-1915255058-line-40)">CONFIG_FILE</text><text class="terminal-1915255058-r2" x="1464" y="996" textLength="12.2" clip-path="url(#terminal-1915255058-line-40)">
|
||||
</text><text class="terminal-1915255058-r2" x="292.8" y="1020.4" textLength="561.2" clip-path="url(#terminal-1915255058-line-41)">write current command line args to config file</text><text class="terminal-1915255058-r2" x="1464" y="1020.4" textLength="12.2" clip-path="url(#terminal-1915255058-line-41)">
|
||||
</text>
|
||||
</g>
|
||||
</g>
|
||||
|
||||
|
Before Width: | Height: | Size: 29 KiB After Width: | Height: | Size: 32 KiB |
@@ -1,7 +1,8 @@
|
||||
from dataclasses import dataclass
|
||||
from typing import Optional
|
||||
import os
|
||||
import argparse
|
||||
|
||||
import configargparse
|
||||
|
||||
try:
|
||||
from rich_argparse import RichHelpFormatter, HelpPreviewAction
|
||||
@@ -19,6 +20,14 @@ SCRIPTDIR = os.path.abspath(os.path.dirname(__file__).removesuffix(PACKAGE))
|
||||
DEFAULT_THEME_PATH = os.path.join(SCRIPTDIR, "templates", "default.css")
|
||||
DEFAULT_AUTHOR = "Author"
|
||||
|
||||
if "APPDATA" in os.environ:
|
||||
CONFIGHOME = os.environ["APPDATA"]
|
||||
elif "XDG_CONFIG_HOME" in os.environ:
|
||||
CONFIGHOME = os.environ["XDG_CONFIG_HOME"]
|
||||
else:
|
||||
CONFIGHOME = os.path.join(os.environ["HOME"], ".config")
|
||||
CONFIGPATH = os.path.join(CONFIGHOME, "StaticGalleryBuilder")
|
||||
|
||||
|
||||
@dataclass(init=True)
|
||||
class Args:
|
||||
@@ -116,9 +125,9 @@ def parse_arguments(version: str) -> Args:
|
||||
"""
|
||||
# fmt: off
|
||||
if RICH:
|
||||
parser = argparse.ArgumentParser(description="generate HTML files for a static image hosting website", formatter_class=RichHelpFormatter)
|
||||
parser = configargparse.ArgumentParser(default_config_files=[CONFIGPATH], add_config_file_help=False, description="generate HTML files for a static image hosting website", formatter_class=RichHelpFormatter)
|
||||
else:
|
||||
parser = argparse.ArgumentParser(description="generate HTML files for a static image hosting website")
|
||||
parser = configargparse.ArgumentParser(default_config_files=[CONFIGPATH], add_config_file_help=False, 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("-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")
|
||||
@@ -127,10 +136,11 @@ def parse_arguments(version: str) -> Args:
|
||||
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("-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('-c', '--config-file', is_config_file=True, help='config file path', metavar="CONFIG_FILE")
|
||||
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")
|
||||
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-extension", help="file extensions to ignore (can be specified multiple times)", action="append", default=[], dest="ignore_extensions", metavar="EXTENSION")
|
||||
parser.add_argument("--regenerate-thumbnails", help="regenerate thumbnails even if they already exist", action="store_true", default=False, dest="regenerate_thumbnails")
|
||||
@@ -140,7 +150,12 @@ def parse_arguments(version: str) -> Args:
|
||||
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("--write-config", type=str, required=False, help="write current command line args to config file", metavar="CONFIG_FILE")
|
||||
parsed_args = parser.parse_args()
|
||||
if parsed_args.write_config:
|
||||
config_path = parsed_args.write_config
|
||||
del parsed_args.write_config
|
||||
parser.write_config_file(parsed_args, [config_path], exit_after=False)
|
||||
# fmt: on
|
||||
_args = Args(
|
||||
author_name=parsed_args.author_name,
|
||||
|
||||
@@ -95,7 +95,8 @@ def css_color_to_hex(css_color: str) -> str:
|
||||
# Helper function to convert HSL tuple to RGB tuple
|
||||
def hsl_to_rgb(hsl: tuple[int, float, float]) -> tuple[int, int, int]:
|
||||
logger.debug("converting hsl tuple to rgb tuple", extra={"hsl": hsl})
|
||||
return tuple(round(c * 255) for c in colorsys.hls_to_rgb(hsl[0] / 360, hsl[1] / 100, hsl[2] / 100))
|
||||
r, g, b = colorsys.hls_to_rgb(hsl[0] / 360, hsl[1] / 100, hsl[2] / 100)
|
||||
return (round(r * 255), round(g * 255), round(b * 255))
|
||||
|
||||
# Regular expression pattern to match CSS colors
|
||||
color_pattern = re.compile(
|
||||
|
||||
158
modules/datatypes/metadata.py
Normal file
158
modules/datatypes/metadata.py
Normal file
@@ -0,0 +1,158 @@
|
||||
from dataclasses import dataclass
|
||||
from typing import List, Optional, Any, Dict, TypeVar, Callable, Type, cast
|
||||
|
||||
T = TypeVar("T")
|
||||
|
||||
|
||||
def from_int(x: Any) -> int:
|
||||
assert isinstance(x, int) and not isinstance(x, bool)
|
||||
return x
|
||||
|
||||
|
||||
def from_str(x: Any) -> str:
|
||||
assert isinstance(x, str)
|
||||
return x
|
||||
|
||||
|
||||
def from_list(f: Callable[[Any], T], x: Any) -> List[T]:
|
||||
assert isinstance(x, list)
|
||||
return [f(y) for y in x]
|
||||
|
||||
|
||||
def from_none(x: Any) -> Any:
|
||||
assert x is None
|
||||
return x
|
||||
|
||||
|
||||
def from_union(fs, x):
|
||||
for f in fs:
|
||||
try:
|
||||
return f(x)
|
||||
except AssertionError:
|
||||
pass
|
||||
assert False
|
||||
|
||||
|
||||
def to_class(c: Type[T], x: Any) -> dict:
|
||||
assert isinstance(x, c)
|
||||
return cast(Any, x).to_dict()
|
||||
|
||||
|
||||
def from_dict(f: Callable[[Any], T], x: Any) -> Dict[str, T]:
|
||||
assert isinstance(x, dict)
|
||||
return {k: f(v) for (k, v) in x.items()}
|
||||
|
||||
|
||||
def from_native_dict(f: Callable[[Any], T], x: Any) -> Dict[Any, T]:
|
||||
assert isinstance(x, dict)
|
||||
return x
|
||||
|
||||
|
||||
@dataclass
|
||||
class ImageMetadata:
|
||||
w: Optional[int]
|
||||
h: Optional[int]
|
||||
tags: Optional[List[str]]
|
||||
exifdata: Optional[Dict[str, Any]]
|
||||
xmp: Optional[Dict[str, Any]]
|
||||
src: str
|
||||
msrc: str
|
||||
name: str
|
||||
title: str
|
||||
tiff: Optional[str] = None
|
||||
raw: Optional[str] = None
|
||||
|
||||
@staticmethod
|
||||
def from_dict(obj: Any) -> "ImageMetadata":
|
||||
assert isinstance(obj, dict)
|
||||
w = from_union([from_int, from_none], obj.get("w"))
|
||||
h = from_union([from_int, from_none], obj.get("h"))
|
||||
tags = from_union([lambda x: from_list(from_str, x), from_none], obj.get("tags"))
|
||||
exifdata = from_union([lambda x: from_native_dict(dict, x), from_none], obj.get("exifdata"))
|
||||
xmp = from_union([lambda x: from_native_dict(dict, x), from_none], obj.get("xmp"))
|
||||
src = from_str(obj.get("src"))
|
||||
msrc = from_str(obj.get("msrc"))
|
||||
name = from_str(obj.get("name"))
|
||||
title = from_str(obj.get("title"))
|
||||
tiff = from_union([from_str, from_none], obj.get("tiff"))
|
||||
raw = from_union([from_str, from_none], obj.get("raw"))
|
||||
return ImageMetadata(w, h, tags, exifdata, xmp, src, msrc, name, title, tiff, raw)
|
||||
|
||||
def to_dict(self) -> dict:
|
||||
result: dict = {}
|
||||
if self.w is not None:
|
||||
result["w"] = from_union([from_int, from_none], self.w)
|
||||
if self.h is not None:
|
||||
result["h"] = from_union([from_int, from_none], self.h)
|
||||
if self.tags is not None:
|
||||
result["tags"] = from_union([lambda x: from_list(from_str, x), from_none], self.tags)
|
||||
result["src"] = from_str(self.src)
|
||||
result["msrc"] = from_str(self.msrc)
|
||||
result["name"] = from_str(self.name)
|
||||
result["title"] = from_str(self.title)
|
||||
if self.tiff is not None:
|
||||
result["tiff"] = from_union([from_str, from_none], self.tiff)
|
||||
if self.raw is not None:
|
||||
result["raw"] = from_union([from_str, from_none], self.raw)
|
||||
if self.exifdata is not None:
|
||||
result["exifdata"] = from_union([lambda x: from_native_dict(dict, x), from_none], self.exifdata)
|
||||
if self.xmp is not None:
|
||||
result["xmp"] = from_union([lambda x: from_native_dict(dict, x), from_none], self.xmp)
|
||||
return result
|
||||
|
||||
|
||||
@dataclass
|
||||
class SubfolderMetadata:
|
||||
url: str
|
||||
name: str
|
||||
metadata: Optional[str] = None
|
||||
thumb: Optional[str] = None
|
||||
|
||||
@staticmethod
|
||||
def from_dict(obj: Any) -> "SubfolderMetadata":
|
||||
assert isinstance(obj, dict)
|
||||
url = from_str(obj.get("url"))
|
||||
name = from_str(obj.get("name"))
|
||||
metadata = from_union([from_none, from_str], obj.get("metadata"))
|
||||
thumb = from_union([from_none, from_str], obj.get("thumb"))
|
||||
return SubfolderMetadata(url, name, metadata, thumb)
|
||||
|
||||
def to_dict(self) -> dict:
|
||||
result: dict = {}
|
||||
result["url"] = from_str(self.url)
|
||||
result["name"] = from_str(self.name)
|
||||
result["metadata"] = from_union([from_none, from_str], self.metadata)
|
||||
result["thumb"] = from_union([from_none, from_str], self.thumb)
|
||||
return result
|
||||
|
||||
|
||||
@dataclass
|
||||
class Metadata:
|
||||
images: Dict[str, ImageMetadata]
|
||||
subfolders: Optional[List[SubfolderMetadata]] = None
|
||||
|
||||
@staticmethod
|
||||
def from_dict(obj: Any) -> "Metadata":
|
||||
assert isinstance(obj, dict)
|
||||
images = from_dict(ImageMetadata.from_dict, obj.get("images"))
|
||||
subfolders = from_union([lambda x: from_list(SubfolderMetadata.from_dict, x), from_none], obj.get("subfolders"))
|
||||
return Metadata(images, subfolders)
|
||||
|
||||
def to_dict(self) -> dict:
|
||||
result: dict = {}
|
||||
result["images"] = from_dict(lambda x: to_class(ImageMetadata, x), self.images)
|
||||
if self.subfolders is not None:
|
||||
result["subfolders"] = from_union([lambda x: from_list(lambda x: to_class(SubfolderMetadata, x), x), from_none], self.subfolders)
|
||||
return result
|
||||
|
||||
def sort(self, reverse=False) -> "Metadata":
|
||||
self.images = {key: self.images[key] for key in sorted(self.images, reverse=reverse)}
|
||||
return self
|
||||
|
||||
|
||||
def top_level_from_dict(s: Any) -> Metadata:
|
||||
return Metadata.from_dict(s)
|
||||
|
||||
|
||||
def top_level_to_dict(x: Metadata) -> Any:
|
||||
return to_class(Metadata, x)
|
||||
@@ -17,6 +17,7 @@ from bs4 import BeautifulSoup
|
||||
from modules.logger import logger
|
||||
from modules import cclicense
|
||||
from modules.argumentparser import Args
|
||||
from modules.datatypes.metadata import Metadata, ImageMetadata, SubfolderMetadata
|
||||
|
||||
# Constants for file paths and exclusions
|
||||
if __package__ is None:
|
||||
@@ -73,7 +74,7 @@ def getxmp(strbuffer: str) -> dict[str, Any]:
|
||||
return {get_name(root.tag): get_value(root)}
|
||||
|
||||
|
||||
def initialize_metadata(folder: str) -> dict[str, dict[str, int]]:
|
||||
def initialize_metadata(folder: str) -> Metadata:
|
||||
"""
|
||||
Initializes the metadata JSON file if it doesn't exist.
|
||||
|
||||
@@ -128,10 +129,10 @@ def initialize_metadata(folder: str) -> dict[str, dict[str, int]]:
|
||||
if "title" not in v:
|
||||
metadata["images"][k]["title"] = v["name"]
|
||||
|
||||
return metadata
|
||||
return Metadata.from_dict(metadata)
|
||||
|
||||
|
||||
def update_metadata(metadata: dict[str, dict[str, Any]], folder: str) -> None:
|
||||
def update_metadata(metadata: Metadata, folder: str) -> None:
|
||||
"""
|
||||
Updates the metadata JSON file.
|
||||
|
||||
@@ -143,14 +144,14 @@ def update_metadata(metadata: dict[str, dict[str, Any]], folder: str) -> None:
|
||||
if metadata:
|
||||
with open(metadata_path, "w", encoding="utf-8") as metadatafile:
|
||||
logger.info("writing metadata file", extra={"file": metadata_path})
|
||||
metadatafile.write(json.dumps(metadata, indent=4))
|
||||
metadatafile.write(json.dumps(metadata.to_dict(), indent=4))
|
||||
else:
|
||||
if os.path.exists(metadata_path):
|
||||
logger.info("deleting empty metadata file", extra={"file": metadata_path})
|
||||
os.remove(metadata_path)
|
||||
|
||||
|
||||
def get_image_info(item: str, folder: str) -> dict[str, Any]:
|
||||
def get_image_info(item: str, folder: str) -> ImageMetadata:
|
||||
"""
|
||||
Extracts image information and EXIF data.
|
||||
|
||||
@@ -172,7 +173,7 @@ def get_image_info(item: str, folder: str) -> dict[str, Any]:
|
||||
except UnidentifiedImageError:
|
||||
logger.error("cannot identify image file", extra={"file": file})
|
||||
print(f"cannot identify image file: {file}")
|
||||
return {"w": None, "h": None, "tags": None, "exifdata": None, "xmp": None}
|
||||
return ImageMetadata(w=None, h=None, tags=[], exifdata=None, xmp=None, src="", msrc="", name="", title="")
|
||||
if exif:
|
||||
logger.info("extracting EXIF data", extra={"file": file})
|
||||
ifd = exif.get_ifd(ExifTags.IFD.Exif)
|
||||
@@ -253,9 +254,11 @@ def get_image_info(item: str, folder: str) -> dict[str, Any]:
|
||||
tags = get_tags(sidecarfile)
|
||||
except Exception as e:
|
||||
logger.error(e)
|
||||
if None in tags:
|
||||
tags.remove(None)
|
||||
return {"w": width, "h": height, "tags": tags, "exifdata": exifdata, "xmp": xmp}
|
||||
if None in tags: # type: ignore
|
||||
tags.remove(None) # type: ignore
|
||||
if not isinstance(tags, list):
|
||||
tags = []
|
||||
return ImageMetadata(w=width, h=height, tags=tags, exifdata=exifdata, xmp=xmp, src="", msrc="", name="", title="")
|
||||
|
||||
|
||||
def nested_dict():
|
||||
@@ -331,12 +334,12 @@ def get_tags(sidecarfile: str) -> list[str]:
|
||||
pass
|
||||
except KeyError:
|
||||
pass
|
||||
if None in tags:
|
||||
tags.remove(None)
|
||||
return tags
|
||||
if None in tags: # type: ignore
|
||||
tags.remove(None) # type: ignore
|
||||
return tags # type: ignore
|
||||
|
||||
|
||||
def process_image(item: str, folder: str, _args: Args, baseurl: str, metadata: dict[str, dict[str, int]], raw: list[str]) -> dict[str, Any]:
|
||||
def process_image(item: str, folder: str, _args: Args, baseurl: str, metadata: Metadata, raw: list[str]) -> tuple[ImageMetadata, Metadata]:
|
||||
"""
|
||||
Processes an image and prepares its data for the HTML template.
|
||||
|
||||
@@ -353,24 +356,21 @@ def process_image(item: str, folder: str, _args: Args, baseurl: str, metadata: d
|
||||
"""
|
||||
extsplit = os.path.splitext(item)
|
||||
sidecarfile = os.path.join(folder, item + ".xmp")
|
||||
if item not in metadata["images"] or _args.reread_metadata:
|
||||
metadata["images"][item] = get_image_info(item, folder)
|
||||
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})
|
||||
try:
|
||||
metadata["images"][item]["tags"] = get_tags(sidecarfile)
|
||||
metadata.images[item].tags = get_tags(sidecarfile)
|
||||
except Exception as e:
|
||||
logger.error(e)
|
||||
|
||||
image = {
|
||||
"src": f"{_args.web_root_url}{baseurl}{urllib.parse.quote(item)}",
|
||||
"msrc": f"{_args.web_root_url}.thumbnails/{baseurl}{urllib.parse.quote(item)}.jpg",
|
||||
"name": item,
|
||||
"w": metadata["images"][item]["w"],
|
||||
"h": metadata["images"][item]["h"],
|
||||
"tags": metadata["images"][item]["tags"],
|
||||
"title": item,
|
||||
}
|
||||
image = metadata.images[item]
|
||||
image.src = f"{_args.web_root_url}{baseurl}{urllib.parse.quote(item)}"
|
||||
image.msrc = f"{_args.web_root_url}.thumbnails/{baseurl}{urllib.parse.quote(item)}.jpg"
|
||||
image.name = item
|
||||
image.title = item
|
||||
|
||||
path = os.path.join(_args.root_directory, ".thumbnails", baseurl, item + ".jpg")
|
||||
if not os.path.exists(path) or _args.regenerate_thumbnails:
|
||||
if os.path.exists(path):
|
||||
@@ -383,17 +383,17 @@ def process_image(item: str, folder: str, _args: Args, baseurl: str, metadata: d
|
||||
url = f"{_args.web_root_url}{baseurl}{urllib.parse.quote(extsplit[0])}{_raw}"
|
||||
if _raw in (".tif", ".tiff"):
|
||||
logger.info("tiff file found", extra={"file": file})
|
||||
image["tiff"] = url
|
||||
image.tiff = url
|
||||
else:
|
||||
logger.info("raw file found", extra={"file": file, "extension": _raw})
|
||||
image["raw"] = url
|
||||
image.raw = url
|
||||
|
||||
metadata["images"][item].update(image)
|
||||
metadata.images[item] = image
|
||||
|
||||
return image, metadata
|
||||
|
||||
|
||||
def generate_html(folder: str, title: str, _args: Args, raw: list[str], version: str, logo: str) -> list[str]:
|
||||
def generate_html(folder: str, title: str, _args: Args, raw: list[str], version: str, logo: str) -> set[str]:
|
||||
"""
|
||||
Generates HTML content for a folder of images.
|
||||
|
||||
@@ -412,22 +412,22 @@ def generate_html(folder: str, title: str, _args: Args, raw: list[str], version:
|
||||
items = sorted(os.listdir(folder))
|
||||
|
||||
contains_files = False
|
||||
images = []
|
||||
subfolders = []
|
||||
subfoldertags = set()
|
||||
images: list[ImageMetadata] = []
|
||||
subfolders: list[SubfolderMetadata] = []
|
||||
subfoldertags: set[str] = set()
|
||||
foldername = folder.removeprefix(_args.root_directory)
|
||||
foldername = f"{foldername}/" if foldername else ""
|
||||
baseurl = urllib.parse.quote(foldername)
|
||||
|
||||
gone = [item for item in metadata["images"] if item not in items]
|
||||
gone = [item for item in metadata.images if item not in items]
|
||||
for gon in gone:
|
||||
del metadata["images"][gon]
|
||||
del metadata.images[gon]
|
||||
|
||||
create_thumbnail_folder(foldername, _args.root_directory)
|
||||
|
||||
logger.info("processing contents", extra={"folder": folder})
|
||||
if not _args.non_interactive_mode:
|
||||
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, leave=False):
|
||||
if item not in EXCLUDES and not item.startswith(".") and os.path.splitext(item)[1][1:].lower() not in _args.ignore_extensions:
|
||||
if os.path.isdir(os.path.join(folder, item)):
|
||||
subfoldertags.update(process_subfolder(item, folder, baseurl, subfolders, _args, raw, version, logo))
|
||||
@@ -455,11 +455,11 @@ def generate_html(folder: str, title: str, _args: Args, raw: list[str], version:
|
||||
if item == "LICENSE":
|
||||
process_license(folder, item)
|
||||
|
||||
metadata["subfolders"] = subfolders
|
||||
metadata.subfolders = subfolders
|
||||
if _args.reverse_sort:
|
||||
metadata["images"] = {key: metadata["images"][key] for key in sorted(metadata["images"], reverse=True)}
|
||||
metadata.sort(reverse=True)
|
||||
else:
|
||||
metadata["images"] = {key: metadata["images"][key] for key in sorted(metadata["images"])}
|
||||
metadata.sort()
|
||||
update_metadata(metadata, folder)
|
||||
|
||||
if should_generate_html(images, contains_files, _args):
|
||||
@@ -485,7 +485,7 @@ def create_thumbnail_folder(foldername: str, root_directory: str) -> None:
|
||||
os.mkdir(thumbnails_path)
|
||||
|
||||
|
||||
def process_subfolder(item: str, folder: str, baseurl: str, subfolders: list[dict[str, str | None]], _args: Args, raw: list[str], version: str, logo: str) -> list[str]:
|
||||
def process_subfolder(item: str, folder: str, baseurl: str, subfolders: list[SubfolderMetadata], _args: Args, raw: list[str], version: str, logo: str) -> set[str]:
|
||||
"""
|
||||
Processes a subfolder.
|
||||
|
||||
@@ -513,10 +513,10 @@ def process_subfolder(item: str, folder: str, baseurl: str, subfolders: list[dic
|
||||
|
||||
if item not in _args.exclude_folders:
|
||||
if not any(fnmatch.fnmatchcase(os.path.join(folder, item), exclude) for exclude in _args.exclude_folders):
|
||||
subfolders.append({"url": subfolder_url, "name": item, "thumb": thumb, "metadata": f"{_args.web_root_url}{baseurl}{urllib.parse.quote(item)}/.metadata.json"})
|
||||
subfolders.append(SubfolderMetadata(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 []
|
||||
subfolders.append(SubfolderMetadata(url=subfolder_url, name=item, thumb=thumb))
|
||||
return set()
|
||||
|
||||
|
||||
def process_license(folder: str, item: str) -> None:
|
||||
@@ -548,7 +548,7 @@ def process_info_file(folder: str, item: str) -> None:
|
||||
info[urllib.parse.quote(folder)] = f.read()
|
||||
|
||||
|
||||
def should_generate_html(images: list[dict[str, Any]], contains_files, _args: Args) -> bool:
|
||||
def should_generate_html(images: list[ImageMetadata], contains_files, _args: Args) -> bool:
|
||||
"""
|
||||
Determines if HTML should be generated.
|
||||
|
||||
@@ -559,7 +559,7 @@ def should_generate_html(images: list[dict[str, Any]], contains_files, _args: Ar
|
||||
Returns:
|
||||
bool: True if HTML should be generated, False otherwise.
|
||||
"""
|
||||
return images or (_args.use_fancy_folders and not contains_files) or (_args.use_fancy_folders and _args.ignore_other_files)
|
||||
return bool(images) or (_args.use_fancy_folders and not contains_files) or (_args.use_fancy_folders and _args.ignore_other_files)
|
||||
|
||||
|
||||
def format_html(html: str) -> str:
|
||||
@@ -568,8 +568,8 @@ def format_html(html: str) -> str:
|
||||
|
||||
|
||||
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]:
|
||||
folder: str, title: str, foldername: str, images: list[ImageMetadata], subfolders: list[SubfolderMetadata], _args: Args, version: str, logo: str, subfoldertags: set[str]
|
||||
) -> set[str]:
|
||||
"""
|
||||
Creates the HTML file using the template.
|
||||
|
||||
@@ -602,15 +602,13 @@ def create_html_file(
|
||||
|
||||
alltags = set()
|
||||
for img in images:
|
||||
if img["tags"]:
|
||||
alltags.update(img["tags"])
|
||||
if img.tags:
|
||||
alltags.update(img.tags)
|
||||
|
||||
alltags.update(set(subfoldertags))
|
||||
alltags.update(subfoldertags)
|
||||
|
||||
folder_info = info.get(urllib.parse.quote(folder), "").split("\n")
|
||||
_info = [i for i in folder_info if len(i) > 1] if folder_info else None
|
||||
if _args.reverse_sort:
|
||||
images.sort(key=lambda i: i["name"], reverse=True)
|
||||
|
||||
folder_license = licens.get(urllib.parse.quote(folder), False)
|
||||
|
||||
@@ -661,7 +659,7 @@ def create_html_file(
|
||||
logger.info("writing formatted html file", extra={"path": html_file})
|
||||
f.write(format_html(content))
|
||||
|
||||
return sorted(alltags)
|
||||
return set(sorted(alltags))
|
||||
|
||||
|
||||
def list_folder(folder: str, title: str, _args: Args, raw: list[str], version: str, logo: str) -> list[tuple[str, str, str]]:
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
beautifulsoup4~=4.13.4
|
||||
CairoSVG~=2.7.1
|
||||
ConfigArgParse~=1.7.1
|
||||
defusedxml~=0.7.1
|
||||
html5lib~=1.1
|
||||
Jinja2~=3.1.6
|
||||
|
||||
2
themes
2
themes
Submodule themes updated: 2d2f96abb3...fa79867f4a
Reference in New Issue
Block a user