mirror of
https://github.com/bookwyrm-social/bookwyrm.git
synced 2024-12-29 11:30:39 +00:00
Merge pull request #402 from mouse-reeve/alt-text
Federate cover alt text
This commit is contained in:
commit
d109ac0626
11 changed files with 78 additions and 57 deletions
|
@ -52,12 +52,29 @@ class Book(ActivitypubMixin, BookWyrmModel):
|
|||
authors = fields.ManyToManyField('Author')
|
||||
# preformatted authorship string for search and easier display
|
||||
author_text = models.CharField(max_length=255, blank=True, null=True)
|
||||
cover = fields.ImageField(upload_to='covers/', blank=True, null=True)
|
||||
cover = fields.ImageField(
|
||||
upload_to='covers/', blank=True, null=True, alt_field='alt_text')
|
||||
first_published_date = fields.DateTimeField(blank=True, null=True)
|
||||
published_date = fields.DateTimeField(blank=True, null=True)
|
||||
|
||||
objects = InheritanceManager()
|
||||
|
||||
@property
|
||||
def edition_info(self):
|
||||
''' properties of this edition, as a string '''
|
||||
items = [
|
||||
self.physical_format,
|
||||
self.languages[0] + ' language' if self.languages and \
|
||||
self.languages[0] != 'English' else None,
|
||||
str(self.published_date.year) if self.published_date else None,
|
||||
]
|
||||
return ', '.join(i for i in items if i)
|
||||
|
||||
@property
|
||||
def alt_text(self):
|
||||
''' image alt test '''
|
||||
return '%s cover (%s)' % (self.title, self.edition_info)
|
||||
|
||||
def save(self, *args, **kwargs):
|
||||
''' can't be abstract for query reasons, but you shouldn't USE it '''
|
||||
if not isinstance(self, Edition) and not isinstance(self, Work):
|
||||
|
|
|
@ -305,18 +305,22 @@ class TagField(ManyToManyField):
|
|||
return items
|
||||
|
||||
|
||||
def image_serializer(value):
|
||||
def image_serializer(value, alt):
|
||||
''' helper for serializing images '''
|
||||
if value and hasattr(value, 'url'):
|
||||
url = value.url
|
||||
else:
|
||||
return None
|
||||
url = 'https://%s%s' % (DOMAIN, url)
|
||||
return activitypub.Image(url=url)
|
||||
return activitypub.Image(url=url, name=alt)
|
||||
|
||||
|
||||
class ImageField(ActivitypubFieldMixin, models.ImageField):
|
||||
''' activitypub-aware image field '''
|
||||
def __init__(self, *args, alt_field=None, **kwargs):
|
||||
self.alt_field = alt_field
|
||||
super().__init__(*args, **kwargs)
|
||||
|
||||
# pylint: disable=arguments-differ
|
||||
def set_field_from_activity(self, instance, data, save=True):
|
||||
''' helper function for assinging a value to the field '''
|
||||
|
@ -326,9 +330,19 @@ class ImageField(ActivitypubFieldMixin, models.ImageField):
|
|||
return
|
||||
getattr(instance, self.name).save(*formatted, save=save)
|
||||
|
||||
def set_activity_from_field(self, activity, instance):
|
||||
value = getattr(instance, self.name)
|
||||
if value is None:
|
||||
return
|
||||
alt_text = getattr(instance, self.alt_field)
|
||||
formatted = self.field_to_activity(value, alt_text)
|
||||
|
||||
def field_to_activity(self, value):
|
||||
return image_serializer(value)
|
||||
key = self.get_activitypub_field()
|
||||
activity[key] = formatted
|
||||
|
||||
|
||||
def field_to_activity(self, value, alt=None):
|
||||
return image_serializer(value, alt)
|
||||
|
||||
|
||||
def field_from_activity(self, value):
|
||||
|
|
|
@ -86,11 +86,11 @@ class Status(OrderedCollectionPageMixin, BookWyrmModel):
|
|||
activity['name'] = self.pure_name
|
||||
activity['type'] = self.pure_type
|
||||
activity['attachment'] = [
|
||||
image_serializer(b.cover) for b in self.mention_books.all() \
|
||||
if b.cover]
|
||||
image_serializer(b.cover, b.alt_text) \
|
||||
for b in self.mention_books.all()[:4] if b.cover]
|
||||
if hasattr(self, 'book'):
|
||||
activity['attachment'].append(
|
||||
image_serializer(self.book.cover)
|
||||
image_serializer(self.book.cover, self.book.alt_text)
|
||||
)
|
||||
return activity
|
||||
|
||||
|
|
|
@ -53,7 +53,8 @@ class User(OrderedCollectionPageMixin, AbstractUser):
|
|||
# name is your display name, which you can change at will
|
||||
name = fields.CharField(max_length=100, default='')
|
||||
avatar = fields.ImageField(
|
||||
upload_to='avatars/', blank=True, null=True, activitypub_field='icon')
|
||||
upload_to='avatars/', blank=True, null=True,
|
||||
activitypub_field='icon', alt_field='alt_text')
|
||||
followers = fields.ManyToManyField(
|
||||
'self',
|
||||
link_only=True,
|
||||
|
@ -90,6 +91,11 @@ class User(OrderedCollectionPageMixin, AbstractUser):
|
|||
last_active_date = models.DateTimeField(auto_now=True)
|
||||
manually_approves_followers = fields.BooleanField(default=False)
|
||||
|
||||
@property
|
||||
def alt_text(self):
|
||||
''' alt text with username '''
|
||||
return 'avatar for %s' % (self.localname or self.username)
|
||||
|
||||
@property
|
||||
def display_name(self):
|
||||
''' show the cleanest version of the user's name possible '''
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
{% load bookwyrm_tags %}
|
||||
<img class="avatar image {% if large %}is-96x96{% else %}is-32x32{% endif %}" src="{% if user.avatar %}/images/{{ user.avatar }}{% else %}/static/images/default_avi.jpg{% endif %}" alt="avatar for {{ user|username }}">
|
||||
<img class="avatar image {% if large %}is-96x96{% else %}is-32x32{% endif %}" src="{% if user.avatar %}/images/{{ user.avatar }}{% else %}/static/images/default_avi.jpg{% endif %}" alt="{{ user.alt_text }}">
|
||||
|
||||
|
|
|
@ -1,13 +1,13 @@
|
|||
{% load bookwyrm_tags %}
|
||||
<div class="cover-container is-{{ size }}">
|
||||
{% if book.cover %}
|
||||
<img class="book-cover" src="/images/{{ book.cover }}" alt="{% include 'snippets/cover_alt.html' with book=book %}">
|
||||
<img class="book-cover" src="/images/{{ book.cover }}" alt="{{ book.alt_text }}">
|
||||
{% else %}
|
||||
<div class="no-cover book-cover">
|
||||
<img class="book-cover" src="/static/images/no_cover.jpg" alt="No cover">
|
||||
<div>
|
||||
<p>{{ book.title }}</p>
|
||||
<p>({{ book|edition_info }})</p>
|
||||
<p>({{ book.edition_info }})</p>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
|
|
@ -1,2 +0,0 @@
|
|||
{% load bookwyrm_tags %}
|
||||
'{{ book.title }}' Cover ({{ book|edition_info }})
|
|
@ -97,20 +97,6 @@ def get_boosted(boost):
|
|||
).get()
|
||||
|
||||
|
||||
@register.filter(name='edition_info')
|
||||
def get_edition_info(book):
|
||||
''' paperback, French language, 1982 '''
|
||||
if not book:
|
||||
return ''
|
||||
items = [
|
||||
book.physical_format if isinstance(book, models.Edition) else None,
|
||||
book.languages[0] + ' language' if book.languages and \
|
||||
book.languages[0] != 'English' else None,
|
||||
str(book.published_date.year) if book.published_date else None,
|
||||
]
|
||||
return ', '.join(i for i in items if i)
|
||||
|
||||
|
||||
@register.filter(name='book_description')
|
||||
def get_book_description(book):
|
||||
''' use the work's text if the book doesn't have it '''
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
''' testing models '''
|
||||
from dateutil.parser import parse
|
||||
from django.test import TestCase
|
||||
from django.utils import timezone
|
||||
|
||||
from bookwyrm import models, settings
|
||||
from bookwyrm.models.book import isbn_10_to_13, isbn_13_to_10
|
||||
|
@ -56,3 +58,27 @@ class Book(TestCase):
|
|||
isbn_13 = '978-1788-16167-1'
|
||||
isbn_10 = isbn_13_to_10(isbn_13)
|
||||
self.assertEqual(isbn_10, '178816167X')
|
||||
|
||||
|
||||
def test_get_edition_info(self):
|
||||
''' text slug about an edition '''
|
||||
book = models.Edition.objects.create(title='Test Edition')
|
||||
self.assertEqual(book.edition_info, '')
|
||||
|
||||
book.physical_format = 'worm'
|
||||
book.save()
|
||||
self.assertEqual(book.edition_info, 'worm')
|
||||
|
||||
book.languages = ['English']
|
||||
book.save()
|
||||
self.assertEqual(book.edition_info, 'worm')
|
||||
|
||||
book.languages = ['Glorbish', 'English']
|
||||
book.save()
|
||||
self.assertEqual(book.edition_info, 'worm, Glorbish language')
|
||||
|
||||
book.published_date = timezone.make_aware(parse('2020'))
|
||||
book.save()
|
||||
self.assertEqual(book.edition_info, 'worm, Glorbish language, 2020')
|
||||
self.assertEqual(
|
||||
book.alt_text, 'Test Edition cover (worm, Glorbish language, 2020)')
|
||||
|
|
|
@ -393,17 +393,19 @@ class ActivitypubFields(TestCase):
|
|||
ContentFile(output.getvalue())
|
||||
)
|
||||
|
||||
output = fields.image_serializer(user.avatar)
|
||||
output = fields.image_serializer(user.avatar, alt='alt text')
|
||||
self.assertIsNotNone(
|
||||
re.match(
|
||||
r'.*\.jpg',
|
||||
output.url,
|
||||
)
|
||||
)
|
||||
self.assertEqual(output.name, 'alt text')
|
||||
self.assertEqual(output.type, 'Image')
|
||||
|
||||
instance = fields.ImageField()
|
||||
|
||||
output = fields.image_serializer(user.avatar, alt=None)
|
||||
self.assertEqual(instance.field_to_activity(user.avatar), output)
|
||||
|
||||
responses.add(
|
||||
|
|
|
@ -158,34 +158,6 @@ class TemplateTags(TestCase):
|
|||
self.assertEqual(boosted, status)
|
||||
|
||||
|
||||
def test_get_edition_info(self):
|
||||
''' text slug about an edition '''
|
||||
self.assertEqual(
|
||||
bookwyrm_tags.get_edition_info(self.book), '')
|
||||
|
||||
self.book.physical_format = 'worm'
|
||||
self.book.save()
|
||||
self.assertEqual(
|
||||
bookwyrm_tags.get_edition_info(self.book), 'worm')
|
||||
|
||||
self.book.languages = ['English']
|
||||
self.book.save()
|
||||
self.assertEqual(
|
||||
bookwyrm_tags.get_edition_info(self.book), 'worm')
|
||||
|
||||
self.book.languages = ['Glorbish', 'English']
|
||||
self.book.save()
|
||||
self.assertEqual(
|
||||
bookwyrm_tags.get_edition_info(self.book),
|
||||
'worm, Glorbish language')
|
||||
|
||||
self.book.published_date = timezone.make_aware(parse('2020'))
|
||||
self.book.save()
|
||||
self.assertEqual(
|
||||
bookwyrm_tags.get_edition_info(self.book),
|
||||
'worm, Glorbish language, 2020')
|
||||
|
||||
|
||||
def test_get_book_description(self):
|
||||
''' grab it from the edition or the parent '''
|
||||
work = models.Work.objects.create(title='Test Work')
|
||||
|
|
Loading…
Reference in a new issue