@@ -1,4 +1,4 @@
import os
import toml
import argparse
import importlib . resources
@@ -19,9 +19,12 @@ def parse_args():
parser = argparse . ArgumentParser (
description = ' Generate a static HTML gallery from a folder of images. '
)
parser . add_argument ( ' --config ' , help = ' Path to a config file (TOML or JSON) ' , default = None )
parser . add_argument ( ' --source ' , required = True , help = ' Source directory with images ' )
parser . add_argument ( ' --output ' , required = True , help = ' Output directory for HTML and images ' )
parser . add_argument ( ' --copyright ' , help = ' Copyright owner name ' )
parser . add_argument ( ' --analytics-id ' , help = ' ID for analytics tracker ' )
parser . add_argument ( ' --analytics-host ' , help = ' Analytics host ' )
return parser . parse_args ( )
def collect_images ( source_dir : Path ) :
@@ -54,7 +57,8 @@ def load_image_template() -> str:
with importlib . resources . files ( ' stills.templates ' ) . joinpath ( ' image.html ' ) . open ( ' r ' , encoding = ' utf-8 ' ) as f :
return f . read ( )
def generate_html ( images , output_dir : Path , author : str | None = None ) :
def generate_html ( images , output_dir : Path , author : str | None = None ,
analytics_id = None , analytics_host = None ) :
template = load_template ( )
image_tags = [ ]
@@ -62,6 +66,19 @@ def generate_html(images, output_dir: Path, author: str | None = None):
photos_dir = output_dir / ' photos '
photos_dir . mkdir ( parents = True , exist_ok = True )
analytics_html = ' '
if analytics_host and analytics_id :
analytics_html = f ' <script defer src= " https:// { analytics_host } /script.js " data-website-id= " { analytics_id } " ></script> '
footer_html = ' '
if author :
footer_html = (
f ' <div class= " footer " > '
f ' © { author } – '
f ' <a href= " https://creativecommons.org/licenses/by-sa/4.0/ " target= " _blank " rel= " noopener noreferrer " >CC BY-SA 4.0</a> '
f ' </div> '
)
for img in reversed ( images ) :
relative_image_path = f ' photos/ { img . name } '
with Image . open ( img ) as im :
@@ -86,16 +103,8 @@ def generate_html(images, output_dir: Path, author: str | None = None):
parts . append ( film )
metadata_html = ' <div class= " metadata " > {} </div> ' . format ( ' , ' . join ( parts ) )
footer_html = ' '
if author :
footer_html = (
f ' <div class= " footer " > '
f ' © { author } – '
f ' <a href= " https://creativecommons.org/licenses/by-sa/4.0/ " target= " _blank " rel= " noopener noreferrer " >CC BY-SA 4.0</a> '
f ' </div> '
)
page_content = image_template . replace ( ' {{ filename }} ' , img . name ) \
. replace ( ' {{ analytics }} ' , analytics_html ) \
. replace ( ' {{ image_src }} ' , f ' ../photos/ { img . name } ' ) \
. replace ( ' {{ metadata }} ' , metadata_html ) \
. replace ( ' {{ footer }} ' , footer_html )
@@ -104,6 +113,7 @@ def generate_html(images, output_dir: Path, author: str | None = None):
images_html = ' \n ' . join ( image_tags )
return template . replace ( ' {{ images }} ' , images_html ) \
. replace ( ' {{ analytics }} ' , analytics_html ) \
. replace ( ' {{ footer }} ' , footer_html )
def copy_images ( images , dest_dir : Path ) :
@@ -121,6 +131,22 @@ def copy_images(images, dest_dir: Path):
def main ( ) :
args = parse_args ( )
# Load config file if provided
config = { }
if args . config :
config_path = Path ( args . config )
if not config_path . is_file ( ) :
raise ValueError ( f ' Config file " { config_path } " not found. ' )
config = toml . load ( config_path )
# Merge config values with command-line args (CLI wins if both provided)
args . source = args . source or config . get ( ' source ' )
args . output = args . output or config . get ( ' output ' )
args . copyright = args . copyright or config . get ( ' copyright ' )
args . analytics_id = args . analytics_id or config . get ( ' analytics_id ' )
args . analytics_host = args . analytics_host or config . get ( ' analytics_host ' )
source_dir = Path ( args . source )
output_dir = Path ( args . output )
photos_dir = output_dir / ' photos '
@@ -130,7 +156,13 @@ def main():
output_dir . mkdir ( parents = True , exist_ok = True )
images = collect_images ( source_dir )
html = generate_html ( images , output_dir , args . copyright )
html = generate_html (
images ,
output_dir ,
args . copyright ,
args . analytics_id ,
args . analytics_host
)
copy_images ( images , photos_dir )