distribusi-verse/distribusi/distribusi.py

237 lines
7.4 KiB
Python
Raw Normal View History

2024-12-04 10:34:07 +01:00
import os
import magic
from PIL import Image
from distribusi.templates.page_template import html_footer, html_head
from distribusi.templates.image_templates import (
image_no_description,
image_with_description,
image_with_alttext,
image_full_figure,
)
from distribusi.mappings import CODE_TYPES, FILE_TYPES, SUB_TYPES
MIME_TYPE = magic.Magic(mime=True)
def _add_alttext(full_path_image):
2024-12-04 10:34:07 +01:00
try:
image_filename_no_ext = os.path.splitext(full_path_image)[0]
alttext_filename = f"{image_filename_no_ext}_alttext.txt"
return _read_matching_text_file(
image_filename_no_ext, alttext_filename
)
except Exception as e:
print(f"exception {e} raised while making alttext")
return
def _add_description(full_path_image):
2024-12-04 10:34:07 +01:00
try:
image_filename_no_ext = os.path.splitext(full_path_image)[0]
description_filename = f"{image_filename_no_ext}_dv_description.txt"
return _read_matching_text_file(
image_filename_no_ext, description_filename
)
except Exception as e:
print(f"exception {e} raised while adding description")
return
def _read_matching_text_file(image_filename_no_ext, filename):
if not os.path.isfile(filename):
return
print(f"{image_filename_no_ext} has {filename}")
with open(filename, "r") as text_file:
return text_file.read()
def _make_thumbnail(full_path_image, name):
2024-12-04 10:34:07 +01:00
if full_path_image.endswith("_thumbnail.jpg"):
return
try:
size = (450, 450)
thumbnail_image = Image.open(full_path_image)
thumbnail_image.thumbnail(size)
if thumbnail_image.mode == "RGBA":
bg = Image.new("RGBA", thumbnail_image.size, (255, 255, 255))
composite = Image.alpha_composite(bg, thumbnail_image)
thumbnail_image = composite.convert("RGB")
image_filename_no_ext = os.path.splitext(full_path_image)[0]
thumbnail_filename = f"{image_filename_no_ext}_thumbnail.jpg"
thumbnail_image.save(thumbnail_filename, format="JPEG")
return os.path.basename(thumbnail_filename)
except Exception as e:
print("Thumbnailer:", e)
return
def _format_div(type_, subtype, tag, name):
2024-12-04 10:34:07 +01:00
id_name = name.split(".")[0].replace(" ", "_")
filename = f'<span class="filename">{name}</span>'
if "image" in type_:
html = '<div id="{}" class="{}">{}</div>'
elif "pdf" in subtype:
html = '<div id="{}" class="{}">{}' + filename + "</div>"
elif "dir" in type_ or "html" in subtype or "unkown-file" in subtype:
html = '<div id="{}" class="{}">{}</div>'
else:
html = '<div id="{}" class="{}">{}' + filename + "</div>"
return html.format(id_name, subtype, tag)
def _check_distribusi_index(index):
2024-12-04 10:34:07 +01:00
"""
check whether a index.html file is generated by distribusi
"""
2024-12-21 12:35:00 +01:00
with open(index, "r") as f:
if '<meta name="generator" content="distribusi" />' in f.read():
return True
return False
2024-12-04 10:34:07 +01:00
def _write_index_html(index, html, cssfile):
2024-12-04 10:34:07 +01:00
with open(index, "w") as index_file:
2024-12-21 12:35:00 +01:00
styled_html_head = html_head.format(cssfile=cssfile)
2024-12-04 10:34:07 +01:00
index_file.write(styled_html_head)
for line in html:
index_file.write(line + "\n")
index_file.write(html_footer)
def _handle_text_files(name, full_path, subtype):
2024-12-04 10:34:07 +01:00
if name.endswith(".html") or subtype == "html":
subtype = "html"
# what types of text files to expand
tag = '<section id="{}">{}</section>'.format(
name, open(full_path).read()
)
elif subtype in CODE_TYPES or name.endswith(".txt"):
# if the plain text is code,
# which types do we wrap in pre-tags?
tag = "<pre>" + open(full_path).read() + "</pre>"
else:
subtype = subtype + " unkown-file"
tag = "<a href='{}'>{}</a>"
# a = FILE_TYPES[type_]
return subtype, tag
def _handle_image_files(name, full_path):
thumbnail_filename = _make_thumbnail(full_path, name)
2024-12-21 12:35:00 +01:00
if thumbnail_filename is None:
return
image_alttext = _add_alttext(full_path)
image_description = _add_description(full_path)
2024-12-21 12:35:00 +01:00
if not image_alttext and not image_description:
return image_no_description.format(
name=name, thumbnail_filename=thumbnail_filename
)
if not image_alttext:
return image_with_description.format(
2024-12-04 10:34:07 +01:00
name=name,
thumbnail_filename=thumbnail_filename,
image_description=image_description,
)
2024-12-21 12:35:00 +01:00
if not image_description:
return image_with_alttext.format(
name=name,
thumbnail_filename=thumbnail_filename,
image_alttext=image_alttext,
)
return image_full_figure.format(
name=name,
thumbnail_filename=thumbnail_filename,
image_alttext=image_alttext,
image_description=image_description,
)
2024-12-04 10:34:07 +01:00
def _remove_existing_index_html(root, files):
2024-12-04 10:34:07 +01:00
index = os.path.join(root, "index.html")
if "index.html" in files:
try:
2024-12-21 12:35:00 +01:00
if check_distribusi_index(index):
2024-12-04 10:34:07 +01:00
os.remove(index)
except Exception as e:
print(e)
return
def _remove_hidden_files_and_folders(dirs, files):
2024-12-04 10:34:07 +01:00
dirs = list(filter(lambda d: not d.startswith("."), dirs))
files = list(filter(lambda f: not f.startswith("."), files))
return dirs, files
def _is_skippable_file(name, cssfile):
2024-12-04 10:34:07 +01:00
if "index.html" in name:
return True
if name.endswith("_thumbnail.jpg"):
return True
if name.endswith("_alttext.txt"):
return True
if name.endswith("_dv_description.txt"):
return True
2024-12-21 12:35:00 +01:00
if cssfile in name:
2024-12-04 10:34:07 +01:00
return True
def distribusify(directory, cssfile):
2024-12-04 10:34:07 +01:00
for root, dirs, files in os.walk(directory):
html = []
dirs, files = _remove_hidden_files_and_folders(dirs, files)
_remove_existing_index_html(root, files)
2024-12-04 10:34:07 +01:00
for name in sorted(files):
if _is_skippable_file(name, cssfile):
2024-12-04 10:34:07 +01:00
continue
full_path = os.path.join(root, name)
mime = MIME_TYPE.from_file(full_path)
type_, subtype = mime.split("/")
alttext = name
if type_ in FILE_TYPES:
match type_:
case "text":
subtype, tag = handle_text_files(
name, full_path, subtype
)
case "image":
tag = _handle_image_files(name, full_path)
2024-12-04 10:34:07 +01:00
if tag is None:
continue
case _:
tag = FILE_TYPES[type_].format(name, alttext)
if subtype in SUB_TYPES:
tag = SUB_TYPES[subtype]
if type_ not in FILE_TYPES and subtype not in SUB_TYPES:
# catch exceptions not yet defined in FILE_TYPES or SUB_TYPES
tag = "<a href='{}'>{}</a>"
tag = tag.replace("{}", name)
html.append(_format_div(type_, subtype, tag, name))
2024-12-04 10:34:07 +01:00
if root != directory:
2024-12-21 12:35:00 +01:00
html.append('<a href="../index.html">../</a>')
2024-12-04 10:34:07 +01:00
for name in sorted(dirs):
2024-12-21 12:35:00 +01:00
tag = "<a href='{}/index.html'>{}</a>".replace("{}", name)
html.insert(0, format_div("dir", "dir", tag, "folder"))
2024-12-04 10:34:07 +01:00
index = os.path.join(root, "index.html")
_write_index_html(index, html, cssfile)