diff options
| author | Shy <[email protected]> | 2026-02-08 10:30:41 -0500 |
|---|---|---|
| committer | Shy <[email protected]> | 2026-02-08 10:30:41 -0500 |
| commit | 5f81d506095852c3f0db5322e67c862f904da3f1 (patch) | |
| tree | 1112345c35eb88d80988ddcd6d04768e90f76ea8 /render.py | |
| download | yuri.directory-5f81d506095852c3f0db5322e67c862f904da3f1.tar.xz yuri.directory-5f81d506095852c3f0db5322e67c862f904da3f1.zip | |
Initial commit
Diffstat (limited to 'render.py')
| -rw-r--r-- | render.py | 209 |
1 files changed, 209 insertions, 0 deletions
diff --git a/render.py b/render.py new file mode 100644 index 0000000..d2ecf2e --- /dev/null +++ b/render.py @@ -0,0 +1,209 @@ +import json +import os +import time +from glob import glob +from itertools import batched + +import jinja2 +from PIL import ImageFile + +from config import WILDCARD_LETTER, THUMBNAIL_CHUNK_SIZE, PROCS, GLOBALS +from imgutils import create_thumbnail_sheet, convert_cover, \ + convert_chapter + +ImageFile.LOAD_TRUNCATED_IMAGES = True +from minify_html import minify +from slugify import slugify +from tqdm import tqdm +from rcssmin import cssmin +from multiprocessing.pool import ThreadPool + +env = jinja2.Environment( + undefined=jinja2.StrictUndefined, +) + +env.filters["slug"] = slugify +env.filters["minify_css"] = cssmin + + +def render_index_pages(path, prefix, index_items, content_rating): + + with open("assets/index.html.jinja") as f: + template = env.from_string(f.read()) + + index_parent_dir = f"{prefix}{('-' + content_rating.lower()) if content_rating else ''}" + + def _work(task): + item, series = task + + index_loc = item.replace(WILDCARD_LETTER, "_") + index_dir = str(os.path.join(path, index_parent_dir, index_loc)) + os.makedirs(index_dir) + + if prefix == "t": + series = sorted(series, key=lambda s: s["score"], reverse=True) + else: + series = sorted(series, key=lambda s: s["sort_name"]) + + thumbnails = [ + { + "cover": glob(os.path.join(path, s["location"], "cover.*"))[0], + "name": s["name"], + "loc": s["location"] + } + for s in series + ] + + for i, chunk in enumerate(batched(thumbnails, THUMBNAIL_CHUNK_SIZE)): + sheet_name = f"{int(time.time()):x}{i:x}" + create_thumbnail_sheet(chunk, os.path.join(index_dir, sheet_name + ".webp")) + + sheet_img = os.path.join(index_parent_dir, index_loc, sheet_name + ".webp") + + for j, tn in enumerate(chunk): + offset_class = f"o{j:x}" + + tn["offset"] = offset_class + tn["img"] = sheet_img + + is_long_list = len(index_items) > 27 + + html = minify(template.render( + name=item, + thumbnails=thumbnails, + parent_loc=index_parent_dir, + loc=index_loc, + prefix=prefix, + index_pages=[ + ( + item.replace("-", " ") if is_long_list else item.upper(), + item, + os.path.join(index_parent_dir, item.replace(WILDCARD_LETTER, "_")), + len(series) > 0 + ) + for item, series in index_items.items() + ], + tags=is_long_list, + rating=content_rating, + **GLOBALS + )) + + with open(os.path.join(index_dir, "index.html"), "w") as f: + f.write(html) + + + with ThreadPool(processes=PROCS) as pool: + tasks = list(index_items.items()) + + for _ in tqdm(pool.imap_unordered(_work, tasks), total=len(tasks)): + pass + + +def render_series_pages(path, index): + with open("assets/series.html.jinja") as f: + template = env.from_string(f.read()) + + def _work(series): + + series_dir = str(os.path.join(path, series["location"])) + os.makedirs(series_dir) + + convert_cover(series["id"] + "_c", series["cover"], series_dir) + + html = minify(template.render( + series_name = series["name"], + loc = series["location"], + chapters = series["chapters"], + tags = list(filter(lambda t: t != "all", series["tags"])), + rating = series["rating"], + **GLOBALS + )) + + with open(os.path.join(series_dir, "index.html"), "w") as f: + #TODO: Debug + # f.write(f"<!-- rm -r data/{slugify(series['name'])} && echo '{series['_url']}' >> history.txt && echo '{series['_url']}' >> bl.txt -->") + f.write(html) + + with ThreadPool(processes=PROCS) as pool: + for _ in tqdm(pool.imap_unordered(_work, index), total=len(index)): + pass + + +def render_chapter_pages(path, index): + + with open("assets/chapter.html.jinja") as f: + template = env.from_string(f.read()) + + + def _work(task): + series, chapter = task + + chapter_dir = str(os.path.join(path, *chapter["location"].split("/"))) + + convert_chapter( + cache_key=f"{series['id']}.{chapter['index']:03d}", + images=chapter["images"], + output_folder=chapter_dir + ) + + images = [ + os.path.basename(filename) + for filename in + sorted(glob(os.path.join(chapter_dir, "*.webp"))) + ] + + html = minify(template.render( + series_name = series["name"], + series_loc = series["location"], + chapter_name = chapter["name"], + loc = chapter["location"], + prev_loc = chapter.get("prev"), + next_loc = chapter.get("next"), + images = images, + **GLOBALS + )) + + with open(os.path.join(chapter_dir, "index.html"), "w") as f: + f.write(html) + + tasks = [] + for series in index: + for chapter in series["chapters"]: + tasks.append((series, chapter)) + + with ThreadPool(processes=PROCS) as pool: + for _ in tqdm(pool.imap_unordered(_work, tasks), total=len(tasks)): + pass + + +def render_home(path): + with open("assets/home.html.jinja") as f: + template = env.from_string(f.read()) + + html = minify(template.render( + **GLOBALS + )) + + with open(os.path.join(path, "index.html"), "w") as f: + f.write(html) + + with open("assets/manifest.json.jinja") as f: + template = env.from_string(f.read()) + + data = json.loads(template.render( + **GLOBALS + )) + + with open(os.path.join(path, "manifest.json"), "w") as f: + json.dump(data, f, sort_keys=True) + +def render_style(path): + with open("assets/style.css.jinja") as f: + template = env.from_string(f.read()) + + css = cssmin(template.render( + **GLOBALS + )) + + with open(os.path.join(path, GLOBALS["style"]), "w") as f: + f.write(css) |
