Compare commits

..

3 commits

9 changed files with 91 additions and 23 deletions

View file

@ -821,6 +821,47 @@ def copy_recursive(src, dest):
else: else:
shutil.copyfile(item, dest / item.name) shutil.copyfile(item, dest / item.name)
memoized_similarities = {}
def similarity(a, b):
if len(a) < len(b):
shorter = a
longer = b
else:
shorter = b
longer = a
if len(shorter) == 0:
return 0
if (shorter, longer) in memoized_similarities:
return memoized_similarities[(shorter, longer)]
options = [similarity(shorter[1:], longer)]
for i in range(1, len(shorter)+1):
match_idx = longer.find(shorter[:i])
if match_idx == -1:
break
options.append(i*i + similarity(shorter[i:], longer[match_idx+i:]))
result = max(options)
memoized_similarities[(shorter, longer)] = result
return result
def top(items, n, key):
if len(items) == 0:
return []
winners = items[:1]
for item in items[1:]:
if len(winners) < n or key(item) > key(winners[-1]):
for i in range(len(winners)):
if key(item) > key(winners[i]):
winners.insert(i, item)
break
if len(winners) > n:
winners.pop()
return winners
def generate(args): def generate(args):
jenv = Environment( jenv = Environment(
loader=PackageLoader("dlibrary"), loader=PackageLoader("dlibrary"),
@ -865,16 +906,28 @@ def generate(args):
'authors': authors, 'authors': authors,
'tags': tags, 'tags': tags,
'thumbnail_path': thumbnail_path, 'thumbnail_path': thumbnail_path,
'images': images,
} }
works.append(work) works.append(work)
work_dir = site_dir / 'works' / work_id for (idx, work) in enumerate(works):
def suggestion_priority(other_work):
if other_work is work:
return -2
if work['series'] and work['series'] == other_work['series']:
return -1
return similarity(work['title'], other_work['title'])
suggested = top(works, 6, suggestion_priority)
work_dir = site_dir / 'works' / work['id']
viewer_dir = work_dir / 'view' viewer_dir = work_dir / 'view'
viewer_dir.mkdir(parents=True, exist_ok=True) viewer_dir.mkdir(parents=True, exist_ok=True)
with open(work_dir / 'index.html', 'w') as f: with open(work_dir / 'index.html', 'w') as f:
f.write(work_template.render(depth=2, work=work, title=title, images=images)) f.write(work_template.render(depth=2, work=work, title=work['title'], suggested=suggested))
with open(viewer_dir / 'index.html', 'w') as f: with open(viewer_dir / 'index.html', 'w') as f:
f.write(viewer_template.render(depth=3, work=work, title=title, images=images)) f.write(viewer_template.render(depth=3, work=work, title=work['title']))
print(f'\x1b[2K\r{idx+1}/{len(works)} works processed...', end='')
def make_categorization(categorization, query, work_filter, work_style_cards=False): def make_categorization(categorization, query, work_filter, work_style_cards=False):
categorization_dir = site_dir / categorization categorization_dir = site_dir / categorization

View file

@ -78,7 +78,7 @@ body {
margin-bottom: 25px; margin-bottom: 25px;
} }
#card-listing { .card-listing {
display: flex; display: flex;
flex-wrap: wrap; flex-wrap: wrap;
justify-content: center; justify-content: center;
@ -115,6 +115,7 @@ body {
flex-wrap: wrap; flex-wrap: wrap;
justify-content: center; justify-content: center;
gap: 30px; gap: 30px;
margin-bottom: 40px;
} }
.work-preview { .work-preview {
@ -157,3 +158,7 @@ body {
display: inline-block; display: inline-block;
margin-bottom: 5px; margin-bottom: 5px;
} }
#suggested-subheader {
text-align: center;
}

View file

@ -32,7 +32,7 @@ document.addEventListener('DOMContentLoaded', () => {
const shuffleButton = document.getElementById('shuffle'); const shuffleButton = document.getElementById('shuffle');
const sortButton = document.getElementById('sort'); const sortButton = document.getElementById('sort');
const searchBox = document.getElementById('search'); const searchBox = document.getElementById('search');
const listContainer = document.getElementById('card-listing'); const listContainer = document.getElementById('main-listing');
let ordering = localStorage.getItem('indexOrdering') || 'dateDesc'; let ordering = localStorage.getItem('indexOrdering') || 'dateDesc';
let shuffleSeed = parseInt(localStorage.getItem('shuffleSeed')) || newSeed(); let shuffleSeed = parseInt(localStorage.getItem('shuffleSeed')) || newSeed();

View file

@ -4,7 +4,7 @@
{% from 'utils.html' import urlcat, index, root with context %} {% from 'utils.html' import urlcat, index, root with context %}
<h1 id="title"><a href="{{ root() }}/{{ index() }}">DLibrary</a> &gt; {{ categorization.capitalize() }}</h1> <h1 id="title"><a href="{{ root() }}/{{ index() }}">DLibrary</a> &gt; {{ categorization.capitalize() }}</h1>
{% include 'nav.html' %} {% include 'nav.html' %}
<div id="card-listing"> <div class="card-listing">
{% for cat in categories %} {% for cat in categories %}
<div class="card {% if not work_style_cards %}category{% endif %}"> <div class="card {% if not work_style_cards %}category{% endif %}">
<a href="{{ urlcat(cat) }}/{{ index() }}"> <a href="{{ urlcat(cat) }}/{{ index() }}">

View file

@ -23,6 +23,6 @@
<div id="search-container"> <div id="search-container">
<input type="text" id="search" placeholder="Search"/> <input type="text" id="search" placeholder="Search"/>
</div> </div>
<div id="card-listing"> <div id="main-listing" class="card-listing">
</div> </div>
{% endblock %} {% endblock %}

View file

@ -1,21 +1,11 @@
{% extends 'base.html' %} {% extends 'base.html' %}
{% block body %} {% block body %}
{% from 'utils.html' import index, root with context %} {% from 'utils.html' import index, root, card with context %}
<h1 id="title"><a href="{{ root() }}/{{ index() }}">DLibrary</a>{% if categorization %} &gt; <a href="{{ root() }}/{{ categorization }}/{{ index() }}">{{ categorization.capitalize() }}</a>{% endif %}{% if title %} &gt; {{ title }}{% endif %}</h1> <h1 id="title"><a href="{{ root() }}/{{ index() }}">DLibrary</a>{% if categorization %} &gt; <a href="{{ root() }}/{{ categorization }}/{{ index() }}">{{ categorization.capitalize() }}</a>{% endif %}{% if title %} &gt; {{ title }}{% endif %}</h1>
{% include 'nav.html' %} {% include 'nav.html' %}
<div id="card-listing"> <div class="card-listing">
{% for work in works %} {% for work in works %}
<div class="card"> {{ card(work) }}
<a href="{{ root() }}/works/{{ work['id'] }}/{{ index() }}">
<img src="{{ root() }}/{{ work['thumbnail_path'] }}">
<div class="card-creators">
[{% if work['circle'] %}{{ work['circle'] }}{% endif %}{% if work['circle'] and work['authors'] %} ({% endif %}{{ ', '.join(work['authors']) }}{% if work['circle'] and work['authors'] %}){% endif %}]
</div>
<div class="card-title">
{{ work['title'] }}
</div>
</a>
</div>
{% endfor %} {% endfor %}
</div> </div>
{% endblock %} {% endblock %}

View file

@ -1,3 +1,17 @@
{% macro root() %}{% if depth == 0 %}.{% else %}..{% endif %}{{ '/..' * (depth-1) }}{% endmacro %} {% macro root() %}{% if depth == 0 %}.{% else %}..{% endif %}{{ '/..' * (depth-1) }}{% endmacro %}
{% macro index() %}{% if not noindex %}index.html{% endif %}{% endmacro %} {% macro index() %}{% if not noindex %}index.html{% endif %}{% endmacro %}
{% macro urlcat(s) %}{{ s | replace('/', ' ') | urlencode }}{% endmacro %} {% macro urlcat(s) %}{{ s | replace('/', ' ') | urlencode }}{% endmacro %}
{% macro card(work) %}
<div class="card">
<a href="{{ root() }}/works/{{ work['id'] }}/{{ index() }}">
<img src="{{ root() }}/{{ work['thumbnail_path'] }}">
<div class="card-creators">
[{% if work['circle'] %}{{ work['circle'] }}{% endif %}{% if work['circle'] and work['authors'] %} ({% endif %}{{ ', '.join(work['authors']) }}{% if work['circle'] and work['authors'] %}){% endif %}]
</div>
<div class="card-title">
{{ work['title'] }}
</div>
</a>
</div>
{% endmacro %}

View file

@ -6,7 +6,7 @@
const WORK_ID = "{{ work['id'] }}"; const WORK_ID = "{{ work['id'] }}";
const INDEX = "{{ index() }}"; const INDEX = "{{ index() }}";
const IMAGES = [ const IMAGES = [
{% for filename in images %} {% for filename in work['images'] %}
"{{ root() }}/images/{{ work['id'] }}/{{ filename }}", "{{ root() }}/images/{{ work['id'] }}/{{ filename }}",
{% endfor %} {% endfor %}
]; ];
@ -18,7 +18,7 @@
<div id="page-num"> <div id="page-num">
<table> <table>
<tr><td id="current-page"></td></tr> <tr><td id="current-page"></td></tr>
<tr><td id="total-pages">{{ images | length }}</td></tr> <tr><td id="total-pages">{{ work['images'] | length }}</td></tr>
</table> </table>
</div> </div>
<div id="duration"></div> <div id="duration"></div>

View file

@ -1,6 +1,6 @@
{% extends 'base.html' %} {% extends 'base.html' %}
{% block body %} {% block body %}
{% from 'utils.html' import urlcat, root, index with context %} {% from 'utils.html' import urlcat, root, index, card with context %}
<h1 id="title"><a href="{{ root() }}/{{ index() }}">DL</a> &gt; {{ title }}</h1> <h1 id="title"><a href="{{ root() }}/{{ index() }}">DL</a> &gt; {{ title }}</h1>
<div class="work-container"> <div class="work-container">
<div class="work-preview"> <div class="work-preview">
@ -41,4 +41,10 @@
{% endif %} {% endif %}
</div> </div>
</div> </div>
<h3 id="suggested-subheader">Suggested works</h3>
<div id="suggested-works" class="card-listing">
{% for sugg in suggested %}
{{ card(sugg) }}
{% endfor %}
</div>
{% endblock %} {% endblock %}