Compare commits
8 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 9de971d2ac | |||
|
e0cb13771c
|
|||
| cd3f2959c0 | |||
| 285d286baf | |||
| 08299abd2a | |||
| d76d2e146d | |||
| f52b0e7778 | |||
| d6a4e1cc82 |
5
.github/workflows/build-release.yml
vendored
@@ -1,6 +1,6 @@
|
|||||||
name: build-release
|
name: build-release
|
||||||
run-name: build-release
|
run-name: build-release
|
||||||
on: [push]
|
on: push
|
||||||
jobs:
|
jobs:
|
||||||
build:
|
build:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
@@ -15,8 +15,9 @@ jobs:
|
|||||||
run: pyinstaller builder.py modules/*.py -n StaticGalleryBuilder -F --add-data files:files --add-data templates:templates --add-data .version:.
|
run: pyinstaller builder.py modules/*.py -n StaticGalleryBuilder -F --add-data files:files --add-data templates:templates --add-data .version:.
|
||||||
- name: Release
|
- name: Release
|
||||||
uses: softprops/action-gh-release@v2
|
uses: softprops/action-gh-release@v2
|
||||||
|
if: startsWith(github.ref, 'refs/tags/')
|
||||||
with:
|
with:
|
||||||
make_latest: true
|
make_latest: true
|
||||||
generate_release_notes: true
|
generate_release_notes: true
|
||||||
files: |
|
files: |
|
||||||
dist/StaticGalleryBuilder
|
dist/StaticGalleryBuilder
|
||||||
|
|||||||
19
builder.py
@@ -17,11 +17,13 @@ from modules.generate_html import list_folder, EXCLUDES
|
|||||||
|
|
||||||
# fmt: off
|
# fmt: off
|
||||||
# Constants
|
# Constants
|
||||||
if __package__ == None:
|
if __package__ is None:
|
||||||
__package__ = ""
|
PACKAGE = ""
|
||||||
SCRIPT_DIR = os.path.abspath(os.path.dirname(__file__).removesuffix(__package__))
|
else:
|
||||||
STATIC_FILES_DIR = os.path.join(os.path.abspath(SCRIPT_DIR), "files")
|
PACKAGE = __package__
|
||||||
VERSION = open(os.path.join(SCRIPT_DIR, ".version"), "r", encoding="utf-8").read()
|
SCRIPTDIR = os.path.abspath(os.path.dirname(__file__).removesuffix(PACKAGE))
|
||||||
|
STATIC_FILES_DIR = os.path.join(os.path.abspath(SCRIPTDIR), "files")
|
||||||
|
VERSION = open(os.path.join(SCRIPTDIR, ".version"), "r", encoding="utf-8").read()
|
||||||
RAW_EXTENSIONS = [
|
RAW_EXTENSIONS = [
|
||||||
".3fr", ".ari", ".arw", ".bay", ".braw", ".crw", ".cr2", ".cr3", ".cap", ".data", ".dcs", ".dcr",
|
".3fr", ".ari", ".arw", ".bay", ".braw", ".crw", ".cr2", ".cr3", ".cap", ".data", ".dcs", ".dcr",
|
||||||
".dng", ".drf", ".eip", ".erf", ".fff", ".gpr", ".iiq", ".k25", ".kdc", ".mdc", ".mef", ".mos",
|
".dng", ".drf", ".eip", ".erf", ".fff", ".gpr", ".iiq", ".k25", ".kdc", ".mdc", ".mef", ".mos",
|
||||||
@@ -94,7 +96,7 @@ def copy_static_files(_args: Args) -> None:
|
|||||||
if "url" in foldericon:
|
if "url" in foldericon:
|
||||||
shutil.copyfile(_args.theme_path, os.path.join(static_dir, "theme.css"))
|
shutil.copyfile(_args.theme_path, os.path.join(static_dir, "theme.css"))
|
||||||
return
|
return
|
||||||
with open(os.path.join(SCRIPT_DIR, foldericon), "r", encoding="utf-8") as f:
|
with open(os.path.join(SCRIPTDIR, foldericon), "r", encoding="utf-8") as f:
|
||||||
svg = f.read()
|
svg = f.read()
|
||||||
if "svg.j2" in foldericon:
|
if "svg.j2" in foldericon:
|
||||||
colorscheme = extract_colorscheme(_args.theme_path)
|
colorscheme = extract_colorscheme(_args.theme_path)
|
||||||
@@ -159,7 +161,7 @@ def get_total_folders(folder: str, _args: Args, _total: int = 0) -> int:
|
|||||||
|
|
||||||
items = sorted(os.listdir(folder))
|
items = sorted(os.listdir(folder))
|
||||||
for item in items:
|
for item in items:
|
||||||
if item not in EXCLUDES and os.path.isdir(os.path.join(folder, item)):
|
if item not in EXCLUDES and os.path.isdir(os.path.join(folder, item)) and not item.startswith("."):
|
||||||
if item not in _args.exclude_folders and not any(fnmatch.fnmatchcase(os.path.join(folder, item), exclude) for exclude in _args.exclude_folders):
|
if item not in _args.exclude_folders and not any(fnmatch.fnmatchcase(os.path.join(folder, item), exclude) for exclude in _args.exclude_folders):
|
||||||
_total = get_total_folders(os.path.join(folder, item), _args, _total)
|
_total = get_total_folders(os.path.join(folder, item), _args, _total)
|
||||||
return _total
|
return _total
|
||||||
@@ -181,6 +183,9 @@ def main() -> None:
|
|||||||
|
|
||||||
try:
|
try:
|
||||||
Path(lock_file).touch()
|
Path(lock_file).touch()
|
||||||
|
if args.regenerate_thumbnails:
|
||||||
|
if os.path.exists(os.path.join(args.root_directory, ".thumbnails")):
|
||||||
|
shutil.rmtree(os.path.join(args.root_directory, ".thumbnails"))
|
||||||
os.makedirs(os.path.join(args.root_directory, ".thumbnails"), exist_ok=True)
|
os.makedirs(os.path.join(args.root_directory, ".thumbnails"), exist_ok=True)
|
||||||
|
|
||||||
copy_static_files(args)
|
copy_static_files(args)
|
||||||
|
|||||||
@@ -1,15 +1,19 @@
|
|||||||
|
from dataclasses import dataclass
|
||||||
from typing import List, Optional
|
from typing import List, Optional
|
||||||
import os
|
import os
|
||||||
import argparse
|
import argparse
|
||||||
from rich_argparse import RichHelpFormatter, HelpPreviewAction
|
from rich_argparse import RichHelpFormatter, HelpPreviewAction
|
||||||
|
|
||||||
|
if __package__ is None:
|
||||||
if __package__ == None:
|
PACKAGE = ""
|
||||||
__package__ = ""
|
else:
|
||||||
DEFAULT_THEME_PATH = os.path.join(os.path.abspath(os.path.dirname(__file__).removesuffix(__package__)), "templates", "default.css")
|
PACKAGE = __package__
|
||||||
|
SCRIPTDIR = os.path.abspath(os.path.dirname(__file__).removesuffix(PACKAGE))
|
||||||
|
DEFAULT_THEME_PATH = os.path.join(SCRIPTDIR, "templates", "default.css")
|
||||||
DEFAULT_AUTHOR = "Author"
|
DEFAULT_AUTHOR = "Author"
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass(init=True)
|
||||||
class Args:
|
class Args:
|
||||||
"""
|
"""
|
||||||
A class to store command-line arguments for the script.
|
A class to store command-line arguments for the script.
|
||||||
@@ -58,6 +62,24 @@ class Args:
|
|||||||
use_fancy_folders: bool
|
use_fancy_folders: bool
|
||||||
web_root_url: str
|
web_root_url: str
|
||||||
|
|
||||||
|
def to_dict(self) -> dict:
|
||||||
|
result: dict = {}
|
||||||
|
result["author_name"] = self.author_name
|
||||||
|
result["exclude_folders"] = self.exclude_folders
|
||||||
|
result["file_extensions"] = self.file_extensions
|
||||||
|
result["generate_webmanifest"] = self.generate_webmanifest
|
||||||
|
result["ignore_other_files"] = self.ignore_other_files
|
||||||
|
if self.license_type is not None:
|
||||||
|
result["license_type"] = self.license_type
|
||||||
|
result["non_interactive_mode"] = self.non_interactive_mode
|
||||||
|
result["regenerate_thumbnails"] = self.regenerate_thumbnails
|
||||||
|
result["root_directory"] = self.root_directory
|
||||||
|
result["site_title"] = self.site_title
|
||||||
|
result["theme_path"] = self.theme_path
|
||||||
|
result["use_fancy_folders"] = self.use_fancy_folders
|
||||||
|
result["web_root_url"] = self.web_root_url
|
||||||
|
return result
|
||||||
|
|
||||||
|
|
||||||
def parse_arguments(version: str) -> Args:
|
def parse_arguments(version: str) -> Args:
|
||||||
"""
|
"""
|
||||||
@@ -73,6 +95,7 @@ def parse_arguments(version: str) -> Args:
|
|||||||
Args
|
Args
|
||||||
An instance of the Args class containing the parsed arguments.
|
An instance of the Args class containing the parsed arguments.
|
||||||
"""
|
"""
|
||||||
|
# fmt: off
|
||||||
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)
|
||||||
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("--generate-help-preview", action=HelpPreviewAction, path="help.svg")
|
parser.add_argument("--generate-help-preview", action=HelpPreviewAction, path="help.svg")
|
||||||
@@ -90,18 +113,20 @@ def parse_arguments(version: str) -> Args:
|
|||||||
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")
|
||||||
parsed_args = parser.parse_args()
|
parsed_args = parser.parse_args()
|
||||||
_args = Args()
|
# fmt: on
|
||||||
_args.author_name = parsed_args.author_name
|
_args = Args(
|
||||||
_args.exclude_folders = parsed_args.exclude_folders
|
author_name=parsed_args.author_name,
|
||||||
_args.file_extensions = parsed_args.file_extensions
|
exclude_folders=parsed_args.exclude_folders,
|
||||||
_args.generate_webmanifest = parsed_args.generate_webmanifest
|
file_extensions=parsed_args.file_extensions,
|
||||||
_args.ignore_other_files = parsed_args.ignore_other_files
|
generate_webmanifest=parsed_args.generate_webmanifest,
|
||||||
_args.license_type = parsed_args.license_type
|
ignore_other_files=parsed_args.ignore_other_files,
|
||||||
_args.non_interactive_mode = parsed_args.non_interactive_mode
|
license_type=parsed_args.license_type,
|
||||||
_args.regenerate_thumbnails = parsed_args.regenerate_thumbnails
|
non_interactive_mode=parsed_args.non_interactive_mode,
|
||||||
_args.root_directory = parsed_args.root_directory
|
regenerate_thumbnails=parsed_args.regenerate_thumbnails,
|
||||||
_args.site_title = parsed_args.site_title
|
root_directory=parsed_args.root_directory,
|
||||||
_args.theme_path = parsed_args.theme_path
|
site_title=parsed_args.site_title,
|
||||||
_args.use_fancy_folders = parsed_args.use_fancy_folders
|
theme_path=parsed_args.theme_path,
|
||||||
_args.web_root_url = parsed_args.web_root_url
|
use_fancy_folders=parsed_args.use_fancy_folders,
|
||||||
|
web_root_url=parsed_args.web_root_url,
|
||||||
|
)
|
||||||
return _args
|
return _args
|
||||||
|
|||||||
@@ -13,8 +13,11 @@ import modules.cclicense as cclicense
|
|||||||
from modules.argumentparser import Args
|
from modules.argumentparser import Args
|
||||||
|
|
||||||
# Constants for file paths and exclusions
|
# Constants for file paths and exclusions
|
||||||
if __package__ == None:
|
if __package__ is None:
|
||||||
__package__ = ""
|
PACKAGE = ""
|
||||||
|
else:
|
||||||
|
PACKAGE = __package__
|
||||||
|
SCRIPTDIR = os.path.abspath(os.path.dirname(__file__).removesuffix(PACKAGE))
|
||||||
FAVICON_PATH = ".static/favicon.ico"
|
FAVICON_PATH = ".static/favicon.ico"
|
||||||
GLOBAL_CSS_PATH = ".static/global.css"
|
GLOBAL_CSS_PATH = ".static/global.css"
|
||||||
EXCLUDES = ["index.html", "manifest.json", "robots.txt"]
|
EXCLUDES = ["index.html", "manifest.json", "robots.txt"]
|
||||||
@@ -23,7 +26,7 @@ EXCLUDES = ["index.html", "manifest.json", "robots.txt"]
|
|||||||
Image.MAX_IMAGE_PIXELS = 933120000
|
Image.MAX_IMAGE_PIXELS = 933120000
|
||||||
|
|
||||||
# Initialize Jinja2 environment for template rendering
|
# Initialize Jinja2 environment for template rendering
|
||||||
env = Environment(loader=FileSystemLoader(os.path.join(os.path.abspath(os.path.dirname(__file__).removesuffix(__package__)), "templates")))
|
env = Environment(loader=FileSystemLoader(os.path.join(SCRIPTDIR, "templates")))
|
||||||
thumbnails: List[Tuple[str, str]] = []
|
thumbnails: List[Tuple[str, str]] = []
|
||||||
info: Dict[str, str] = {}
|
info: Dict[str, str] = {}
|
||||||
pbardict: Dict[str, tqdm] = {}
|
pbardict: Dict[str, tqdm] = {}
|
||||||
|
|||||||
@@ -14,16 +14,19 @@ except ImportError:
|
|||||||
SVGSUPPORT = False
|
SVGSUPPORT = False
|
||||||
|
|
||||||
from modules.argumentparser import Args
|
from modules.argumentparser import Args
|
||||||
from modules.css_color import css_color_to_hex, extract_theme_color, extract_colorscheme
|
from modules.css_color import extract_theme_color, extract_colorscheme
|
||||||
|
|
||||||
# Define constants for static files directory and icon sizes
|
# Define constants for static files directory and icon sizes
|
||||||
if __package__ == None:
|
if __package__ is None:
|
||||||
__package__ = ""
|
PACKAGE = ""
|
||||||
STATIC_FILES_DIR = os.path.join(os.path.abspath(os.path.dirname(__file__).removesuffix(__package__)), "files")
|
else:
|
||||||
|
PACKAGE = __package__
|
||||||
|
SCRIPTDIR = os.path.abspath(os.path.dirname(__file__).removesuffix(PACKAGE))
|
||||||
|
STATIC_FILES_DIR = os.path.join(SCRIPTDIR, "files")
|
||||||
ICON_SIZES = ["36x36", "48x48", "72x72", "96x96", "144x144", "192x192", "512x512"]
|
ICON_SIZES = ["36x36", "48x48", "72x72", "96x96", "144x144", "192x192", "512x512"]
|
||||||
|
|
||||||
# Initialize Jinja2 environment for template rendering
|
# Initialize Jinja2 environment for template rendering
|
||||||
env = Environment(loader=FileSystemLoader(os.path.join(os.path.abspath(os.path.dirname(__file__).removesuffix(__package__)), "templates")))
|
env = Environment(loader=FileSystemLoader(os.path.join(SCRIPTDIR, "templates")))
|
||||||
|
|
||||||
|
|
||||||
class Icon:
|
class Icon:
|
||||||
|
|||||||
@@ -4,4 +4,5 @@ numpy==2.0.0
|
|||||||
pillow==10.4.0
|
pillow==10.4.0
|
||||||
pyinstaller==6.9.0
|
pyinstaller==6.9.0
|
||||||
rich-argparse==1.5.2
|
rich-argparse==1.5.2
|
||||||
|
setuptools==70.3.0
|
||||||
tqdm==4.66.4
|
tqdm==4.66.4
|
||||||
@@ -12,19 +12,17 @@
|
|||||||
--bcolor2: #20123b;
|
--bcolor2: #20123b;
|
||||||
--bcolor3: #2b1753;
|
--bcolor3: #2b1753;
|
||||||
--bcolor4: #321c64;
|
--bcolor4: #321c64;
|
||||||
--gradient: linear-gradient(
|
--gradient: linear-gradient(80deg,
|
||||||
80deg,
|
var(--bcolor2) 0%,
|
||||||
var(--bcolor2) 0%,
|
var(--color3) 1%,
|
||||||
var(--color3) 1%,
|
var(--color4) 2%,
|
||||||
var(--color4) 2%,
|
var(--color5) 3%,
|
||||||
var(--color5) 3%,
|
var(--color1) 4%,
|
||||||
var(--color1) 4%,
|
var(--color1) 96%,
|
||||||
var(--color1) 96%,
|
var(--color5) 97%,
|
||||||
var(--color5) 97%,
|
var(--color4) 98%,
|
||||||
var(--color4) 98%,
|
var(--color3) 99%,
|
||||||
var(--color3) 99%,
|
var(--bcolor2) 100%);
|
||||||
var(--bcolor2) 100%
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
body {
|
body {
|
||||||
@@ -110,4 +108,4 @@ body {
|
|||||||
background-color: var(--color2);
|
background-color: var(--color2);
|
||||||
color: var(--bcolor2);
|
color: var(--bcolor2);
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
}
|
}
|
||||||
|
Before Width: | Height: | Size: 1.5 MiB After Width: | Height: | Size: 1.5 MiB |
|
Before Width: | Height: | Size: 1.5 MiB After Width: | Height: | Size: 1.5 MiB |
|
Before Width: | Height: | Size: 1.5 MiB After Width: | Height: | Size: 1.5 MiB |
|
Before Width: | Height: | Size: 1.5 MiB After Width: | Height: | Size: 1.5 MiB |
|
Before Width: | Height: | Size: 1.5 MiB After Width: | Height: | Size: 1.5 MiB |
|
Before Width: | Height: | Size: 1.5 MiB After Width: | Height: | Size: 1.5 MiB |
|
Before Width: | Height: | Size: 1.5 MiB After Width: | Height: | Size: 1.5 MiB |
|
Before Width: | Height: | Size: 1.5 MiB After Width: | Height: | Size: 1.5 MiB |
|
Before Width: | Height: | Size: 1.5 MiB After Width: | Height: | Size: 1.5 MiB |
|
Before Width: | Height: | Size: 1.5 MiB After Width: | Height: | Size: 1.5 MiB |
|
Before Width: | Height: | Size: 1.5 MiB After Width: | Height: | Size: 1.5 MiB |
|
Before Width: | Height: | Size: 1.5 MiB After Width: | Height: | Size: 1.5 MiB |
|
Before Width: | Height: | Size: 1.5 MiB After Width: | Height: | Size: 1.5 MiB |
|
Before Width: | Height: | Size: 1.5 MiB After Width: | Height: | Size: 1.5 MiB |
|
Before Width: | Height: | Size: 1.5 MiB After Width: | Height: | Size: 1.5 MiB |
|
Before Width: | Height: | Size: 1.5 MiB After Width: | Height: | Size: 1.5 MiB |
|
Before Width: | Height: | Size: 1.5 MiB After Width: | Height: | Size: 1.5 MiB |
|
Before Width: | Height: | Size: 1.5 MiB After Width: | Height: | Size: 1.5 MiB |
|
Before Width: | Height: | Size: 1.5 MiB After Width: | Height: | Size: 1.5 MiB |