From b5412d5d3399d6d345d9cd2153296115eb0ae8f1 Mon Sep 17 00:00:00 2001 From: xenofem Date: Tue, 23 Jan 2024 00:55:06 -0500 Subject: [PATCH 01/10] tweak back card styling for series list --- dlibrary/dlibrary.py | 4 +++- dlibrary/templates/categorization.html | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/dlibrary/dlibrary.py b/dlibrary/dlibrary.py index a24638d..46ffd99 100755 --- a/dlibrary/dlibrary.py +++ b/dlibrary/dlibrary.py @@ -347,7 +347,7 @@ def publish(args): with open(viewer_dir / 'index.html', 'w') as f: f.write(viewer_template.render(depth=3, work=work, title=title, images=images)) - def make_categorization(categorization, query, work_filter): + def make_categorization(categorization, query, work_filter, work_style_cards=False): categorization_dir = args.destdir / 'site' / categorization cats = [cat for (cat,) in cur.execute(query)] @@ -374,6 +374,7 @@ def publish(args): categorization=categorization, categories=cats, samples=cat_samples, + work_style_cards=work_style_cards, )) make_categorization( @@ -395,6 +396,7 @@ def publish(args): 'series', 'SELECT DISTINCT series FROM works WHERE series NOT NULL ORDER BY series', lambda series: lambda work: work['series'] == series, + work_style_cards=True, ) with resources.as_file(resources.files("dlibrary")) as r: diff --git a/dlibrary/templates/categorization.html b/dlibrary/templates/categorization.html index 3a5a3ac..3a0519c 100644 --- a/dlibrary/templates/categorization.html +++ b/dlibrary/templates/categorization.html @@ -6,7 +6,7 @@ {% include 'nav.html' %}
{% for cat in categories %} -
+
{{ cat }} From e3eeded952f79924ab4e29aa021173f7e53da6fb Mon Sep 17 00:00:00 2001 From: xenofem Date: Tue, 23 Jan 2024 01:34:08 -0500 Subject: [PATCH 02/10] mess around with css to make the work page not suck on phones --- dlibrary/static/dlibrary.css | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/dlibrary/static/dlibrary.css b/dlibrary/static/dlibrary.css index d02110d..03c78d4 100644 --- a/dlibrary/static/dlibrary.css +++ b/dlibrary/static/dlibrary.css @@ -51,12 +51,19 @@ body { .work-container { display: flex; + flex-wrap: wrap; justify-content: center; gap: 30px; } +.work-preview img { + max-width: 100%; +} + .work-info { - max-width: min(50%, 500px); + flex-basis: 40%; + flex-grow: 1; + max-width: 500px; } .work-info td, .work-info th { From fb7d275ebb8b3c1a3cf8a455fdf3cbf167dfd7f0 Mon Sep 17 00:00:00 2001 From: xenofem Date: Tue, 23 Jan 2024 15:32:55 -0500 Subject: [PATCH 03/10] add tap zones for mobile viewing --- dlibrary/static/viewer.css | 23 +++++++++++++++++++++++ dlibrary/static/viewer.js | 14 +++++++++++--- dlibrary/templates/viewer.html | 5 +++++ 3 files changed, 39 insertions(+), 3 deletions(-) diff --git a/dlibrary/static/viewer.css b/dlibrary/static/viewer.css index 9045ee9..31181aa 100644 --- a/dlibrary/static/viewer.css +++ b/dlibrary/static/viewer.css @@ -4,3 +4,26 @@ html, body { padding: 0; margin: 0; } + +#button-next, #button-prev { + position: fixed; + bottom: 0px; + width: 30vw; + height: 100vh; +} + +#button-next { + left: 0px; +} + +#button-prev { + right: 0px; +} + +#button-back { + position: fixed; + top: 0px; + left: 30vw; + width: 40vw; + height: 20vh; +} diff --git a/dlibrary/static/viewer.js b/dlibrary/static/viewer.js index f2dd772..a3d0240 100644 --- a/dlibrary/static/viewer.js +++ b/dlibrary/static/viewer.js @@ -78,6 +78,12 @@ document.addEventListener('DOMContentLoaded', () => { } } + function exitToWork() { + changeDuration(duration, true); + localStorage.setItem(`${WORK_ID}-currentPage`, 0); + window.location.href = "../"; + } + changePage(currentPage); changeDuration(duration, paused); @@ -111,10 +117,12 @@ document.addEventListener('DOMContentLoaded', () => { } break; case 13: //enter - changeDuration(duration, true); - localStorage.setItem(`${WORK_ID}-currentPage`, 0); - window.location.href = "../"; + exitToWork(); break; } }; + + document.getElementById("button-next").onclick = () => { changePage(currentPage + 1); }; + document.getElementById("button-prev").onclick = () => { changePage(currentPage - 1); }; + document.getElementById("button-back").onclick = exitToWork; }); diff --git a/dlibrary/templates/viewer.html b/dlibrary/templates/viewer.html index 77f8076..2457287 100644 --- a/dlibrary/templates/viewer.html +++ b/dlibrary/templates/viewer.html @@ -16,5 +16,10 @@
+
+
+
+
+
{% endblock %} From 1f15abed9a8bab30a81a41cc7e7230dc61f948b1 Mon Sep 17 00:00:00 2001 From: xenofem Date: Tue, 23 Jan 2024 15:54:17 -0500 Subject: [PATCH 04/10] add more detailed help and allow configuring destdir with environment variable --- dlibrary/dlibrary.py | 111 +++++++++++++++++++++++++++++++++++++++---- 1 file changed, 101 insertions(+), 10 deletions(-) diff --git a/dlibrary/dlibrary.py b/dlibrary/dlibrary.py index 46ffd99..e6e910a 100755 --- a/dlibrary/dlibrary.py +++ b/dlibrary/dlibrary.py @@ -4,10 +4,12 @@ import argparse import asyncio import importlib_resources as resources from pathlib import Path +from os import getenv from os.path import relpath, splitext import re import shutil import sqlite3 +import textwrap from urllib.parse import urlparse import zipfile @@ -301,7 +303,7 @@ def copy_contents(src, dest): for item in src.iterdir(): shutil.copyfile(item, dest / item.name) -def publish(args): +def generate(args): jenv = Environment( loader=PackageLoader("dlibrary"), autoescape=select_autoescape() @@ -408,12 +410,33 @@ def publish(args): con.close() -argparser = argparse.ArgumentParser(prog='dlibrary') +argparser = argparse.ArgumentParser( + prog='dlibrary', + formatter_class=argparse.RawDescriptionHelpFormatter, + description=textwrap.dedent("""\ + Organize DRM-free works purchased from DLSite into a library + that can be viewed in a web browser. + + Intended workflow: + - `extract` a collection of zipfiles downloaded from DLSite + into DLibrary's data directory, giving each work its own + subfolder. + - `fetch` metadata and thumbnail images for extracted works + from DLSite. + - `collate` and/or `manual-collate` extracted works, + producing a single sequence of image files (or symlinks + into the extracted data, when possible) for each work. + - Manually adjust works' `metadata` when necessary. + - `generate` a static website providing a catalog and viewer + for all collated works. + """), +) + argparser.add_argument( '-d', '--destdir', type=Path, - default=Path('./dlibrary'), - help='directory to store dlibrary content and metadata to (default: ./dlibrary)', + default=Path(getenv('DLIBRARY_DIR', './dlibrary')), + help='directory to store dlibrary content and metadata to (default: $DLIBRARY_DIR or ./dlibrary)', ) subparsers = argparser.add_subparsers(title="subcommands", required=True) @@ -435,23 +458,79 @@ parser_extract.set_defaults(func=extract) parser_fetch = subparsers.add_parser('fetch', help='fetch metadata and thumbnails') parser_fetch.set_defaults(func=fetch) -parser_collate = subparsers.add_parser('collate', help='collate a single sequence of image files for each work') +parser_collate = subparsers.add_parser( + 'collate', + help='collate each work into a sequence of image files', + formatter_class=argparse.RawDescriptionHelpFormatter, + description=textwrap.dedent("""\ + For each extracted work that has not already been collated, + DLibrary will attempt to intuit its structure as follows: + + - Enter the work's directory. If the directory contains + nothing except a single subdirectory (ignoring a few types + of files that are definitely not relevant), traverse + downwards repeatedly. + - If the current directory contains nothing except a single + PDF (again, ignoring irrelevant files), attempt to extract + a series of images from the PDF. This process expects that + each page of the PDF consists of a single embedded image, + which will be extracted at full resolution. Support for + more complex PDFs is not yet implemented. + - If the current directory contains nothing except image + files, and the image files are named in a way that clearly + indicates a complete numerical order (each filename + consists of a shared prefix followed by a distinct + number), symlink files in the inferred order. + - Otherwise, skip processing this work for now. + + DLibrary can be given "collation hints" which provide + alternative starting points for this search process. A hint + is a path under $DLIBRARY_DIR/extract/[work id]/ + indicating a different directory or PDF file to begin the + search process for that work, rather than starting at the + top level of the extracted data. There can be at most one + hint per work; for more complicated scenarios where a work + includes multiple folders that need to be collated together, + or where filenames do not clearly indicate an ordering, use + `manual-collate` instead. + """), +) parser_collate.add_argument( 'hints', metavar='PATH', type=Path, nargs='*', - help='manually-specified paths of subdirectories or PDFs within extraction folders, at most one per work', + help='paths within extraction folders as collation hints' ) parser_collate.set_defaults(func=collate) -parser_manual_collate = subparsers.add_parser('manual-collate', help='collate a specific work manually, specifying all paths to include') +parser_manual_collate = subparsers.add_parser( + 'manual-collate', + help='collate a single work manually', + formatter_class=argparse.RawDescriptionHelpFormatter, + description=textwrap.dedent("""\ + All provided paths must be under $DLIBRARY_DIR/extract/[work id]/ + for the work being manually collated. `manual-collate` can + only handle one work at a time. Paths are used as follows: + + - If a path is a directory, all *image files* immediately + inside that directory will be appended to the sequence. If + files are named in a way which indicates a clear ordering, + that ordering will be used. Otherwise, filenames will be + sorted lexicographically. Non-image files and + subdirectories will be ignored. + - If a path is an image file, that image file will be + appended to the sequence. + - If a path is a PDF file, page images will be extracted + from that PDF and appended to the sequence. +"""), +) parser_manual_collate.add_argument( 'paths', metavar='PATH', type=Path, nargs='+', - help='paths of files (images to symlink, pdfs to extract) or directories (symlink all images in the directory, no recursion, best-effort sorting)' + help='paths within a single work to be collated in sequence', ) parser_manual_collate.set_defaults(func=manual_collate) @@ -464,8 +543,20 @@ parser_metadata.add_argument( ) parser_metadata.set_defaults(func=metadata) -parser_publish = subparsers.add_parser('publish', help='generate HTML/CSS/JS for library site') -parser_publish.set_defaults(func=publish) +parser_generate = subparsers.add_parser( + 'generate', + help='generate HTML/CSS/JS for library site', + formatter_class=argparse.RawDescriptionHelpFormatter, + description=textwrap.dedent("""\ + The static site will be generated under $DLIBRARY_DIR/site/ + and can be served by pointing an HTTP server at that + directory. Note that some files inside the static site + hierarchy will be symlinks into $DLIBRARY_DIR/extract/ + outside the site hierarchy, so make sure your HTTP server + will allow those symlinks to be read. + """), +) +parser_generate.set_defaults(func=generate) def main(): args = argparser.parse_args() From ecb63ced83cc7a220e68b7e0a6409f7f05141e3f Mon Sep 17 00:00:00 2001 From: xenofem Date: Tue, 23 Jan 2024 15:56:25 -0500 Subject: [PATCH 05/10] include work description in work overview --- dlibrary/templates/work.html | 1 + 1 file changed, 1 insertion(+) diff --git a/dlibrary/templates/work.html b/dlibrary/templates/work.html index b9e568c..68bbae6 100644 --- a/dlibrary/templates/work.html +++ b/dlibrary/templates/work.html @@ -35,6 +35,7 @@ {% endif %} + {{ work['description'] }}
{% endblock %} From 528ad4e6f22d8a2c480cd1520b1f7c0552244438 Mon Sep 17 00:00:00 2001 From: xenofem Date: Tue, 23 Jan 2024 16:42:10 -0500 Subject: [PATCH 06/10] make viewer RTL-agnostic --- dlibrary/static/viewer.css | 6 +++--- dlibrary/static/viewer.js | 25 +++++++++++++++++++++---- dlibrary/templates/viewer.html | 4 ++-- 3 files changed, 26 insertions(+), 9 deletions(-) diff --git a/dlibrary/static/viewer.css b/dlibrary/static/viewer.css index 31181aa..0955210 100644 --- a/dlibrary/static/viewer.css +++ b/dlibrary/static/viewer.css @@ -5,18 +5,18 @@ html, body { margin: 0; } -#button-next, #button-prev { +#button-left, #button-right { position: fixed; bottom: 0px; width: 30vw; height: 100vh; } -#button-next { +#button-left { left: 0px; } -#button-prev { +#button-right { right: 0px; } diff --git a/dlibrary/static/viewer.js b/dlibrary/static/viewer.js index a3d0240..3c2e1a4 100644 --- a/dlibrary/static/viewer.js +++ b/dlibrary/static/viewer.js @@ -5,6 +5,7 @@ document.addEventListener('DOMContentLoaded', () => { let paused = true; let interval; let elapsed = 0; + let rtl = (localStorage.getItem(`${WORK_ID}-rtl`) !== "false"); function startTimer() { if (interval) { @@ -78,6 +79,22 @@ document.addEventListener('DOMContentLoaded', () => { } } + function left() { + if (currentPage === 0) { + rtl = true; + localStorage.setItem(`${WORK_ID}-rtl`, rtl); + } + changePage(currentPage + (rtl ? 1 : -1)); + } + + function right() { + if (currentPage === 0) { + rtl = false; + localStorage.setItem(`${WORK_ID}-rtl`, rtl); + } + changePage(currentPage + (rtl ? -1 : 1)); + } + function exitToWork() { changeDuration(duration, true); localStorage.setItem(`${WORK_ID}-currentPage`, 0); @@ -93,7 +110,7 @@ document.addEventListener('DOMContentLoaded', () => { changeDuration(duration, !paused); break; case 37: //left - changePage(currentPage - 1); + left(); break; case 38: //up if (2 <= duration && duration <= 10) { @@ -105,7 +122,7 @@ document.addEventListener('DOMContentLoaded', () => { } break; case 39: //right - changePage(currentPage + 1); + right(); break; case 40: //down if (duration < 10) { @@ -122,7 +139,7 @@ document.addEventListener('DOMContentLoaded', () => { } }; - document.getElementById("button-next").onclick = () => { changePage(currentPage + 1); }; - document.getElementById("button-prev").onclick = () => { changePage(currentPage - 1); }; + document.getElementById("button-left").onclick = left; + document.getElementById("button-right").onclick = right; document.getElementById("button-back").onclick = exitToWork; }); diff --git a/dlibrary/templates/viewer.html b/dlibrary/templates/viewer.html index 2457287..c1de14e 100644 --- a/dlibrary/templates/viewer.html +++ b/dlibrary/templates/viewer.html @@ -17,8 +17,8 @@
-
-
+
+
From 323ce158f9c42c2cf262c3b2d863b40823dfdf15 Mon Sep 17 00:00:00 2001 From: xenofem Date: Tue, 23 Jan 2024 17:35:01 -0500 Subject: [PATCH 07/10] fancier recursive copy function we didn't end up needing --- dlibrary/dlibrary.py | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/dlibrary/dlibrary.py b/dlibrary/dlibrary.py index e6e910a..986a824 100755 --- a/dlibrary/dlibrary.py +++ b/dlibrary/dlibrary.py @@ -298,10 +298,13 @@ def metadata(args): con.close() -def copy_contents(src, dest): +def copy_recursive(src, dest): dest.mkdir(parents=True, exist_ok=True) for item in src.iterdir(): - shutil.copyfile(item, dest / item.name) + if item.is_dir() and not item.is_symlink(): + copy_recursive(item, dest / item.name) + else: + shutil.copyfile(item, dest / item.name) def generate(args): jenv = Environment( @@ -402,7 +405,7 @@ def generate(args): ) with resources.as_file(resources.files("dlibrary")) as r: - copy_contents(r / 'static', args.destdir / 'site' / 'static') + copy_recursive(r / 'static', args.destdir / 'site' / 'static') with open(args.destdir / 'site' / 'index.html', 'w') as f: f.write(list_template.render(depth=0, works=works)) From 79b946889d087b10c3e10f365bb85c332d784cd7 Mon Sep 17 00:00:00 2001 From: xenofem Date: Tue, 23 Jan 2024 17:35:33 -0500 Subject: [PATCH 08/10] make tap zones vaguely discoverable --- dlibrary/static/viewer.css | 23 ++++++++++++++++++----- dlibrary/static/viewer.js | 17 +++++++++++++---- dlibrary/templates/viewer.html | 18 +++++++++++++++--- 3 files changed, 46 insertions(+), 12 deletions(-) diff --git a/dlibrary/static/viewer.css b/dlibrary/static/viewer.css index 0955210..f521e83 100644 --- a/dlibrary/static/viewer.css +++ b/dlibrary/static/viewer.css @@ -5,23 +5,36 @@ html, body { margin: 0; } -#button-left, #button-right { +.tap { + background: #000000; + opacity: 0.8; + position: fixed; + animation: 2s linear forwards fade; + display: flex; + justify-content: center; + align-items: center; +} + +@keyframes fade { + to { opacity: 0; } +} + +#tap-left, #tap-right { position: fixed; bottom: 0px; width: 30vw; height: 100vh; } -#button-left { +#tap-left { left: 0px; } -#button-right { +#tap-right { right: 0px; } -#button-back { - position: fixed; +#tap-back { top: 0px; left: 30vw; width: 40vw; diff --git a/dlibrary/static/viewer.js b/dlibrary/static/viewer.js index 3c2e1a4..f6bc30d 100644 --- a/dlibrary/static/viewer.js +++ b/dlibrary/static/viewer.js @@ -101,10 +101,18 @@ document.addEventListener('DOMContentLoaded', () => { window.location.href = "../"; } + function hideTapZones() { + for (const el of document.getElementsByClassName('tap')) { + el.style.opacity = 0; + } + } + changePage(currentPage); changeDuration(duration, paused); - document.onkeydown = event =>{ + document.onkeydown = event => { + hideTapZones(); + switch (event.keyCode) { case 32: //space changeDuration(duration, !paused); @@ -139,7 +147,8 @@ document.addEventListener('DOMContentLoaded', () => { } }; - document.getElementById("button-left").onclick = left; - document.getElementById("button-right").onclick = right; - document.getElementById("button-back").onclick = exitToWork; + document.onclick = hideTapZones; + document.getElementById("tap-left").onclick = left; + document.getElementById("tap-right").onclick = right; + document.getElementById("tap-back").onclick = exitToWork; }); diff --git a/dlibrary/templates/viewer.html b/dlibrary/templates/viewer.html index c1de14e..9ef6315 100644 --- a/dlibrary/templates/viewer.html +++ b/dlibrary/templates/viewer.html @@ -17,9 +17,21 @@
-
-
-
+
+ + + +
+
+ + + +
+
+ + + +
{% endblock %} From a825162deebc34446f0042b4f109f81cf08278b0 Mon Sep 17 00:00:00 2001 From: xenofem Date: Tue, 23 Jan 2024 21:01:02 -0500 Subject: [PATCH 09/10] use links ending in index.html for easier file:// viewing --- dlibrary/static/viewer.js | 2 +- dlibrary/templates/base.html | 2 +- dlibrary/templates/categorization.html | 8 ++++---- dlibrary/templates/list.html | 8 ++++---- dlibrary/templates/nav.html | 4 ++-- dlibrary/templates/utils.html | 3 ++- dlibrary/templates/viewer.html | 9 +++++---- dlibrary/templates/work.html | 16 ++++++++-------- 8 files changed, 27 insertions(+), 25 deletions(-) diff --git a/dlibrary/static/viewer.js b/dlibrary/static/viewer.js index f6bc30d..ebf9c62 100644 --- a/dlibrary/static/viewer.js +++ b/dlibrary/static/viewer.js @@ -98,7 +98,7 @@ document.addEventListener('DOMContentLoaded', () => { function exitToWork() { changeDuration(duration, true); localStorage.setItem(`${WORK_ID}-currentPage`, 0); - window.location.href = "../"; + window.location.href = `../${INDEX}`; } function hideTapZones() { diff --git a/dlibrary/templates/base.html b/dlibrary/templates/base.html index 40cb671..1fb0b0a 100644 --- a/dlibrary/templates/base.html +++ b/dlibrary/templates/base.html @@ -6,7 +6,7 @@ {% block title %}{% if title %}{{ title }} - {% else %}{% endif %}DLibrary{% endblock %} - + {% block head %}{% endblock %} diff --git a/dlibrary/templates/categorization.html b/dlibrary/templates/categorization.html index 3a0519c..321e7ed 100644 --- a/dlibrary/templates/categorization.html +++ b/dlibrary/templates/categorization.html @@ -1,18 +1,18 @@ {% extends "base.html" %} {% block title %}{{ categorization.capitalize() }} - DLibrary{% endblock %} {% block body %} -{% from 'utils.html' import urlcat, root with context %} -

DLibrary > {{ categorization.capitalize() }}

+{% from 'utils.html' import urlcat, index, root with context %} +

DLibrary > {{ categorization.capitalize() }}

{% include 'nav.html' %}
{% for cat in categories %} diff --git a/dlibrary/templates/list.html b/dlibrary/templates/list.html index f882c21..d0e1139 100644 --- a/dlibrary/templates/list.html +++ b/dlibrary/templates/list.html @@ -1,13 +1,13 @@ {% extends 'base.html' %} {% block body %} -{% from 'utils.html' import root with context %} -

DLibrary{% if categorization %} > {{ categorization.capitalize() }}{% endif %}{% if title %} > {{ title }}{% endif %}

+{% from 'utils.html' import index, root with context %} +

DLibrary{% if categorization %} > {{ categorization.capitalize() }}{% endif %}{% if title %} > {{ title }}{% endif %}

{% include 'nav.html' %}
{% for work in works %}
- - + +
[{% if work['circle'] %}{{ work['circle'] }}{% endif %}{% if work['circle'] and work['authors'] %} ({% endif %}{{ ', '.join(work['authors']) }}{% if work['circle'] and work['authors'] %}){% endif %}]
diff --git a/dlibrary/templates/nav.html b/dlibrary/templates/nav.html index cbd9527..62af956 100644 --- a/dlibrary/templates/nav.html +++ b/dlibrary/templates/nav.html @@ -1,2 +1,2 @@ -{% from 'utils.html' import root with context %} -
+{% from 'utils.html' import root, index with context %} + diff --git a/dlibrary/templates/utils.html b/dlibrary/templates/utils.html index 10ccd00..161dc38 100644 --- a/dlibrary/templates/utils.html +++ b/dlibrary/templates/utils.html @@ -1,2 +1,3 @@ -{% macro root() %}{% for i in range(depth) %}../{% endfor %}{% endmacro %} +{% macro root() %}{% if depth == 0 %}.{% else %}..{% endif %}{{ '/..' * (depth-1) }}{% endmacro %} +{% macro index() %}{% if not noindex %}index.html{% endif %}{% endmacro %} {% macro urlcat(s) %}{{ s | replace('/', ' ') | urlencode }}{% endmacro %} diff --git a/dlibrary/templates/viewer.html b/dlibrary/templates/viewer.html index 9ef6315..dc521e9 100644 --- a/dlibrary/templates/viewer.html +++ b/dlibrary/templates/viewer.html @@ -1,16 +1,17 @@ {% extends 'base.html' %} -{% from 'utils.html' import root with context %} +{% from 'utils.html' import index, root with context %} {% block head %} - + - + {% endblock %} {% block body %}
{% for filename in images %} - + {% endfor %}
diff --git a/dlibrary/templates/work.html b/dlibrary/templates/work.html index 68bbae6..3717b17 100644 --- a/dlibrary/templates/work.html +++ b/dlibrary/templates/work.html @@ -1,11 +1,11 @@ {% extends 'base.html' %} {% block body %} -{% from 'utils.html' import urlcat, root with context %} -

DL > {{ title }}

+{% from 'utils.html' import urlcat, root, index with context %} +

DL > {{ title }}

@@ -13,25 +13,25 @@ {% if work['circle'] %} Circle - {{ work['circle'] }} + {{ work['circle'] }} {% endif %} {% if work['authors'] %} Authors - {% for author in work['authors'] %}{{ author }} {% endfor %} + {% for author in work['authors'] %}{{ author }} {% endfor %} {% endif %} {% if work['tags'] %} Tags - {% for tag in work['tags'] %}{{ tag }} {% endfor %} + {% for tag in work['tags'] %}{{ tag }} {% endfor %} {% endif %} {% if work['series'] %} Series - {{ work['series'] }} + {{ work['series'] }} {% endif %} From b437fcc79e43a1dee28f1355019ee4018fd938ee Mon Sep 17 00:00:00 2001 From: xenofem Date: Tue, 23 Jan 2024 21:06:56 -0500 Subject: [PATCH 10/10] add MIT License or something --- LICENSE | 19 +++++++++++++++++++ pyproject.toml | 3 +++ 2 files changed, 22 insertions(+) create mode 100644 LICENSE diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..f2a3e3f --- /dev/null +++ b/LICENSE @@ -0,0 +1,19 @@ +Copyright (c) 2024 xenofem + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. \ No newline at end of file diff --git a/pyproject.toml b/pyproject.toml index 9f2b3a6..58df9bd 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,9 @@ [project] name = "dlibrary" version = "0.1" +description = "Cataloging tool and viewer for downloaded DLSite purchases" +license = {file = "LICENSE"} +authors = [{name = "xenofem"}] dependencies = [ "requests", "PyMuPDF",