From 4549edb5693d67c9a2e73de812014b83c0a21912 Mon Sep 17 00:00:00 2001 From: Joachim Date: Sat, 17 Dec 2022 18:43:48 +0100 Subject: [PATCH 01/11] Bump Pillow minimum version --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index c0a6b6078..60b372ebb 100644 --- a/requirements.txt +++ b/requirements.txt @@ -12,7 +12,7 @@ environs==9.3.4 flower==1.2.0 libsass==0.21.0 Markdown==3.3.3 -Pillow>=9.0.0 +Pillow>=9.3.0 psycopg2==2.8.4 pycryptodome==3.9.4 python-dateutil==2.8.1 From 86c810ee37d9d750e6626eafd1230b964201078b Mon Sep 17 00:00:00 2001 From: Joachim Date: Sat, 17 Dec 2022 18:44:17 +0100 Subject: [PATCH 02/11] Change ANTIALIAS to Resampling.LANCZOS --- bookwyrm/preview_images.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bookwyrm/preview_images.py b/bookwyrm/preview_images.py index d20145cd3..1578a25f6 100644 --- a/bookwyrm/preview_images.py +++ b/bookwyrm/preview_images.py @@ -172,7 +172,7 @@ def generate_instance_layer(content_width): instance_text_x = 0 if logo_img: - logo_img.thumbnail((50, 50), Image.ANTIALIAS) + logo_img.thumbnail((50, 50), Image.Resampling.LANCZOS) instance_layer.paste(logo_img, (0, 0)) @@ -273,7 +273,7 @@ def generate_preview_image( # Cover try: inner_img_layer = Image.open(picture) - inner_img_layer.thumbnail((inner_img_width, inner_img_height), Image.ANTIALIAS) + inner_img_layer.thumbnail((inner_img_width, inner_img_height), Image.Resampling.LANCZOS) color_thief = ColorThief(picture) dominant_color = color_thief.get_color(quality=1) except: # pylint: disable=bare-except From 684e84f5c3b80579ed96de3081d44eb83c064fd5 Mon Sep 17 00:00:00 2001 From: Joachim Date: Sat, 17 Dec 2022 19:24:07 +0100 Subject: [PATCH 03/11] Remove deprecated Font.getsize() https://pillow.readthedocs.io/en/stable/deprecations.html#font-size-and-offset-methods --- bookwyrm/preview_images.py | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/bookwyrm/preview_images.py b/bookwyrm/preview_images.py index 1578a25f6..5229de041 100644 --- a/bookwyrm/preview_images.py +++ b/bookwyrm/preview_images.py @@ -183,7 +183,7 @@ def generate_instance_layer(content_width): (instance_text_x, 10), site.name, font=font_instance, fill=TEXT_COLOR ) - line_width = 50 + 10 + font_instance.getsize(site.name)[0] + line_width = 50 + 10 + round(font_instance.getlength(site.name)) line_layer = Image.new( "RGBA", (line_width, 2), color=(*(ImageColor.getrgb(TEXT_COLOR)), 50) @@ -253,10 +253,12 @@ def generate_default_inner_img(): default_cover_draw = ImageDraw.Draw(default_cover) text = "no image :(" - text_dimensions = font_cover.getsize(text) + text_left, text_top, text_right, text_bottom = font_cover.getbbox(text) + text_width, text_height = text_right - text_left, text_bottom - text_top + text_coords = ( - math.floor((inner_img_width - text_dimensions[0]) / 2), - math.floor((inner_img_height - text_dimensions[1]) / 2), + math.floor((inner_img_width - text_width) / 2), + math.floor((inner_img_height - text_height) / 2), ) default_cover_draw.text(text_coords, text, font=font_cover, fill="white") From 003d1425f967c318959121f3d85ac53d78e4be69 Mon Sep 17 00:00:00 2001 From: Joachim Date: Sat, 17 Dec 2022 19:32:10 +0100 Subject: [PATCH 04/11] Fix comments --- bookwyrm/preview_images.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/bookwyrm/preview_images.py b/bookwyrm/preview_images.py index 5229de041..49700f1cc 100644 --- a/bookwyrm/preview_images.py +++ b/bookwyrm/preview_images.py @@ -100,7 +100,7 @@ def generate_texts_layer(texts, content_width): text_y = 0 if "text_zero" in texts and texts["text_zero"]: - # Text one (Book title) + # Text zero (Site preview domain name) text_zero = get_wrapped_text(texts["text_zero"], font_text_zero, content_width) text_layer_draw.multiline_text( @@ -113,7 +113,7 @@ def generate_texts_layer(texts, content_width): text_y = text_y + 26 if "text_one" in texts and texts["text_one"]: - # Text one (Book title) + # Text one (Book/Site title, User display name) text_one = get_wrapped_text(texts["text_one"], font_text_one, content_width) text_layer_draw.multiline_text( @@ -126,7 +126,7 @@ def generate_texts_layer(texts, content_width): text_y = text_y + 26 if "text_two" in texts and texts["text_two"]: - # Text one (Book subtitle) + # Text two (Book subtitle) text_two = get_wrapped_text(texts["text_two"], font_text_two, content_width) text_layer_draw.multiline_text( @@ -139,7 +139,7 @@ def generate_texts_layer(texts, content_width): text_y = text_y + 26 if "text_three" in texts and texts["text_three"]: - # Text three (Book authors) + # Text three (Book authors, Site tagline, User address) text_three = get_wrapped_text( texts["text_three"], font_text_three, content_width ) From bf82b4cd3517ae351064b0b282a09c6c6dee206e Mon Sep 17 00:00:00 2001 From: Joachim Date: Sat, 17 Dec 2022 19:52:52 +0100 Subject: [PATCH 05/11] Replace Font.getsize_multiline with Draw.multiline_textbbox --- bookwyrm/preview_images.py | 34 +++++++++++++++++++++++++--------- 1 file changed, 25 insertions(+), 9 deletions(-) diff --git a/bookwyrm/preview_images.py b/bookwyrm/preview_images.py index 49700f1cc..ad3b16d95 100644 --- a/bookwyrm/preview_images.py +++ b/bookwyrm/preview_images.py @@ -71,20 +71,30 @@ def get_wrapped_text(text, font, content_width): low = 0 high = len(text) + im = Image.new("RGB", (100, 100)) + draw = ImageDraw.Draw(im) + try: # ideal length is determined via binary search while low < high: mid = math.floor(low + high) wrapped_text = textwrap.fill(text, width=mid) - width = font.getsize_multiline(wrapped_text)[0] + + left, top, right, bottom = draw.multiline_textbbox( + (0, 0), wrapped_text, font=font + ) + width = right - left + height = bottom - top + if width < content_width: low = mid else: high = mid - 1 except AttributeError: wrapped_text = text + height = 26 - return wrapped_text + return wrapped_text, height def generate_texts_layer(texts, content_width): @@ -101,46 +111,52 @@ def generate_texts_layer(texts, content_width): if "text_zero" in texts and texts["text_zero"]: # Text zero (Site preview domain name) - text_zero = get_wrapped_text(texts["text_zero"], font_text_zero, content_width) + text_zero, text_height = get_wrapped_text( + texts["text_zero"], font_text_zero, content_width + ) text_layer_draw.multiline_text( (0, text_y), text_zero, font=font_text_zero, fill=TEXT_COLOR ) try: - text_y = text_y + font_text_zero.getsize_multiline(text_zero)[1] + 16 + text_y = text_y + text_height + 16 except (AttributeError, IndexError): text_y = text_y + 26 if "text_one" in texts and texts["text_one"]: # Text one (Book/Site title, User display name) - text_one = get_wrapped_text(texts["text_one"], font_text_one, content_width) + text_one, text_height = get_wrapped_text( + texts["text_one"], font_text_one, content_width + ) text_layer_draw.multiline_text( (0, text_y), text_one, font=font_text_one, fill=TEXT_COLOR ) try: - text_y = text_y + font_text_one.getsize_multiline(text_one)[1] + 16 + text_y = text_y + text_height + 16 except (AttributeError, IndexError): text_y = text_y + 26 if "text_two" in texts and texts["text_two"]: # Text two (Book subtitle) - text_two = get_wrapped_text(texts["text_two"], font_text_two, content_width) + text_two, text_height = get_wrapped_text( + texts["text_two"], font_text_two, content_width + ) text_layer_draw.multiline_text( (0, text_y), text_two, font=font_text_two, fill=TEXT_COLOR ) try: - text_y = text_y + font_text_one.getsize_multiline(text_two)[1] + 16 + text_y = text_y + text_height + 16 except (AttributeError, IndexError): text_y = text_y + 26 if "text_three" in texts and texts["text_three"]: # Text three (Book authors, Site tagline, User address) - text_three = get_wrapped_text( + text_three, text_height = get_wrapped_text( texts["text_three"], font_text_three, content_width ) From 26f8710c6ff28f27db4468c4b86c77e14dfb090b Mon Sep 17 00:00:00 2001 From: Joachim Date: Sat, 17 Dec 2022 19:52:58 +0100 Subject: [PATCH 06/11] Black --- bookwyrm/preview_images.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/bookwyrm/preview_images.py b/bookwyrm/preview_images.py index ad3b16d95..b2c3e627e 100644 --- a/bookwyrm/preview_images.py +++ b/bookwyrm/preview_images.py @@ -291,7 +291,9 @@ def generate_preview_image( # Cover try: inner_img_layer = Image.open(picture) - inner_img_layer.thumbnail((inner_img_width, inner_img_height), Image.Resampling.LANCZOS) + inner_img_layer.thumbnail( + (inner_img_width, inner_img_height), Image.Resampling.LANCZOS + ) color_thief = ColorThief(picture) dominant_color = color_thief.get_color(quality=1) except: # pylint: disable=bare-except From c5eb27a7c5228bc52012914805ccbda7d5a47785 Mon Sep 17 00:00:00 2001 From: Joachim Date: Sat, 17 Dec 2022 20:27:39 +0100 Subject: [PATCH 07/11] Lint --- bookwyrm/preview_images.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/bookwyrm/preview_images.py b/bookwyrm/preview_images.py index b2c3e627e..99e2d8177 100644 --- a/bookwyrm/preview_images.py +++ b/bookwyrm/preview_images.py @@ -71,8 +71,7 @@ def get_wrapped_text(text, font, content_width): low = 0 high = len(text) - im = Image.new("RGB", (100, 100)) - draw = ImageDraw.Draw(im) + draw = ImageDraw.Draw(Image.new("RGB", (100, 100))) try: # ideal length is determined via binary search @@ -156,7 +155,7 @@ def generate_texts_layer(texts, content_width): if "text_three" in texts and texts["text_three"]: # Text three (Book authors, Site tagline, User address) - text_three, text_height = get_wrapped_text( + text_three, _ = get_wrapped_text( texts["text_three"], font_text_three, content_width ) From f5ebdd4ba10914258d7a94573a17a1c333f9864c Mon Sep 17 00:00:00 2001 From: Christof Dorner Date: Mon, 19 Dec 2022 18:30:12 +0100 Subject: [PATCH 08/11] Add compile_themes management command --- .../management/commands/compile_themes.py | 48 +++++++++++++++++++ 1 file changed, 48 insertions(+) create mode 100644 bookwyrm/management/commands/compile_themes.py diff --git a/bookwyrm/management/commands/compile_themes.py b/bookwyrm/management/commands/compile_themes.py new file mode 100644 index 000000000..95c6699ba --- /dev/null +++ b/bookwyrm/management/commands/compile_themes.py @@ -0,0 +1,48 @@ +""" Our own command to all scss themes """ +import glob +import os + +import sass + +from django.core.management.base import BaseCommand + +from sass_processor.apps import APPS_INCLUDE_DIRS +from sass_processor.processor import SassProcessor +from sass_processor.utils import get_custom_functions + +from bookwyrm import settings + + +class Command(BaseCommand): + """command-line options""" + + help = "SCSS compile all BookWyrm themes" + + # pylint: disable=unused-argument + def handle(self, *args, **options): + """compile""" + themes_dir = os.path.join( + settings.BASE_DIR, "bookwyrm", "static", "css", "themes", "*.scss" + ) + for theme_scss in glob.glob(themes_dir): + basename, _ = os.path.splitext(theme_scss) + theme_css = f"{basename}.css" + self.compile_sass(theme_scss, theme_css) + + def compile_sass(self, sass_path, css_path): + compile_kwargs = { + "filename": sass_path, + "include_paths": SassProcessor.include_paths + APPS_INCLUDE_DIRS, + "custom_functions": get_custom_functions(), + "precision": getattr(settings, "SASS_PRECISION", 8), + "output_style": getattr( + settings, + "SASS_OUTPUT_STYLE", + "nested" if settings.DEBUG else "compressed", + ), + } + + content = sass.compile(**compile_kwargs) + with open(css_path, "w") as f: + f.write(content) + self.stdout.write("Compiled SASS/SCSS file: '{0}'\n".format(sass_path)) From 8bb5c867eb477d438b9e26c5aec268197476e041 Mon Sep 17 00:00:00 2001 From: Christof Dorner Date: Mon, 19 Dec 2022 18:35:34 +0100 Subject: [PATCH 09/11] Add compile_themes to bw-dev --- bw-dev | 7 +++++++ complete_bwdev.fish | 2 ++ complete_bwdev.sh | 1 + complete_bwdev.zsh | 1 + 4 files changed, 11 insertions(+) diff --git a/bw-dev b/bw-dev index ef5dec813..7ce1755a1 100755 --- a/bw-dev +++ b/bw-dev @@ -92,6 +92,7 @@ case "$CMD" in migrate migrate django_celery_beat initdb + runweb python manage.py compile_themes runweb python manage.py collectstatic --no-input admin_code ;; @@ -122,6 +123,9 @@ case "$CMD" in prod_error runweb pytest -n 3 --cov-report term-missing "$@" ;; + compile_themes) + runweb python manage.py compile_themes + ;; collectstatic) runweb python manage.py collectstatic --no-input ;; @@ -203,6 +207,7 @@ case "$CMD" in docker-compose build # ./update.sh runweb python manage.py migrate + runweb python manage.py compile_themes runweb python manage.py collectstatic --no-input docker-compose up -d docker-compose restart web @@ -256,6 +261,7 @@ case "$CMD" in migrate migrate django_celery_beat initdb + runweb python manage.py compile_themes runweb python manage.py collectstatic --no-input admin_code ;; @@ -283,6 +289,7 @@ case "$CMD" in echo " dbshell" echo " restart_celery" echo " pytest [path]" + echo " compile_themes" echo " collectstatic" echo " makemessages" echo " compilemessages [locale]" diff --git a/complete_bwdev.fish b/complete_bwdev.fish index e680ede43..6f4172972 100644 --- a/complete_bwdev.fish +++ b/complete_bwdev.fish @@ -14,6 +14,7 @@ dbshell \ restart_celery \ pytest \ pytest_coverage_report \ +compile_themes \ collectstatic \ makemessages \ compilemessages \ @@ -54,6 +55,7 @@ __bw_complete "$commands" "shell" "open the Python shell withi __bw_complete "$commands" "dbshell" "open the database shell within the web container" __bw_complete "$commands" "restart_celery" "restart the celery container" __bw_complete "$commands" "pytest" "run unit tests" +__bw_complete "$commands" "compile_themes" "compile themes css files" __bw_complete "$commands" "collectstatic" "copy changed static files into the installation" __bw_complete "$commands" "makemessages" "extract all localizable messages from the code" __bw_complete "$commands" "compilemessages" "compile .po localization files to .mo" diff --git a/complete_bwdev.sh b/complete_bwdev.sh index 7976b2126..365b58369 100644 --- a/complete_bwdev.sh +++ b/complete_bwdev.sh @@ -11,6 +11,7 @@ dbshell restart_celery pytest pytest_coverage_report +compile_themes collectstatic makemessages compilemessages diff --git a/complete_bwdev.zsh b/complete_bwdev.zsh index e9c8028c1..5df0c6533 100644 --- a/complete_bwdev.zsh +++ b/complete_bwdev.zsh @@ -13,6 +13,7 @@ dbshell restart_celery pytest pytest_coverage_report +compile_themes collectstatic makemessages compilemessages From 744bd33d990e20bddcdd970092aa4fa7d827da4b Mon Sep 17 00:00:00 2001 From: Christof Dorner Date: Mon, 19 Dec 2022 18:35:55 +0100 Subject: [PATCH 10/11] Add compile_themes command to themes admin page instructions --- bookwyrm/templates/settings/themes.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bookwyrm/templates/settings/themes.html b/bookwyrm/templates/settings/themes.html index 628b04d77..c0dfd7b42 100644 --- a/bookwyrm/templates/settings/themes.html +++ b/bookwyrm/templates/settings/themes.html @@ -29,7 +29,7 @@ {% trans "Copy the theme file into the bookwyrm/static/css/themes directory on your server from the command line." %}
  • - {% trans "Run ./bw-dev collectstatic." %} + {% trans "Run ./bw-dev compile_themes and ./bw-dev collectstatic." %}
  • {% trans "Add the file name using the form below to make it available in the application interface." %} From aefc02e3eeac22a21d7ffe123064df152d4aa427 Mon Sep 17 00:00:00 2001 From: Christof Dorner Date: Mon, 19 Dec 2022 18:37:44 +0100 Subject: [PATCH 11/11] Disable sass processor when not in debug mode --- bookwyrm/settings.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/bookwyrm/settings.py b/bookwyrm/settings.py index 0780f8c54..d960c6071 100644 --- a/bookwyrm/settings.py +++ b/bookwyrm/settings.py @@ -193,7 +193,8 @@ STATICFILES_FINDERS = [ ] SASS_PROCESSOR_INCLUDE_FILE_PATTERN = r"^.+\.[s]{0,1}(?:a|c)ss$" -SASS_PROCESSOR_ENABLED = True +# when debug is disabled, make sure to compile themes once with `./bw-dev compile_themes` +SASS_PROCESSOR_ENABLED = DEBUG # minify css is production but not dev if not DEBUG: