Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update Image Format.classnames to be Format.classname #10987

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.txt
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@ Changelog
* Maintenance: Implement `date_since` in `get_most_popular` inside `search_promotions.models.Query` (TopDevPros)
* Maintenance: Refactor generic view subclasses to better reuse the generic templates and breadcrumbs (Sage Abdullah)
* Maintenance: Adopt consistent `classname` (not `classnames`) attributes for all `MenuItem` usage, including deprecation warnings (LB (Ben) Johnston)
* Maintenance: Adopt consistent `classname` (not `classnames`) attribute within the `wagtail.images.formats.Format` instance, including deprecation warnings (LB (Ben) Johnston)
* Maintenance: Deprecate `context` argument of `construct_snippet_listing_buttons` hook (Sage Abdullah)
* Maintenance: Deprecate legacy moderation system (Sage Abdullah)

Expand Down
4 changes: 2 additions & 2 deletions docs/advanced_topics/customisation/page_editing_interface.md
Original file line number Diff line number Diff line change
Expand Up @@ -115,11 +115,11 @@ The unique key used to identify the format. To unregister this format, call `unr
**`label`**\
The label used in the chooser form when inserting the image into the `RichTextField`.

**`classnames`**\
**`classname`**\
The string to assign to the `class` attribute of the generated `<img>` tag.
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These docs are really only for the args, as these are not kwargs the naming here does not matter but I thought it would be good to update nonetheless.

I have intentionally not included a changed in 5.2 note as I thought this would just cause more confusion.


```{note}
Any class names you provide must have CSS rules matching them written separately, as part of the front end CSS code. Specifying a `classnames` value of `left` will only ensure that class is output in the generated markup, it won't cause the image to align itself left.
Any class names you provide must have CSS rules matching them written separately, as part of the front end CSS code. Specifying a `classname` value of `left` will only ensure that class is output in the generated markup, it won't cause the image to align itself left.
```

**`filter_spec`**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ class SubclassedImageFormat(Format):


register_image_format(
SubclassedImageFormat('subclassed_format', 'Subclassed Format', classnames, filter_spec)
SubclassedImageFormat('subclassed_format', 'Subclassed Format', 'image-classes object-contain', filter_spec)
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just updated the example code to be more 'real world', instead of some uncleared variable classname.

)
```

Expand Down
30 changes: 30 additions & 0 deletions docs/releases/5.2.md
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,7 @@ depth: 1
* Implement `date_since` in `get_most_popular` inside `search_promotions.models.Query` (TopDevPros)
* Refactor generic view subclasses to better reuse the generic templates and breadcrumbs (Sage Abdullah)
* Adopt consistent `classname` (not `classnames`) attributes for all `MenuItem` usage, including deprecation warnings (LB (Ben) Johnston)
* Adopt consistent `classname` (not `classnames`) attribute within the `wagtail.images.formats.Format` instance, including deprecation warnings (LB (Ben) Johnston)
* Deprecate `context` argument of `construct_snippet_listing_buttons` hook (Sage Abdullah)
* Deprecate legacy moderation system (Sage Abdullah)

Expand Down Expand Up @@ -398,3 +399,32 @@ def my_view(request):
The [`construct_snippet_listing_buttons`](construct_snippet_listing_buttons) hook no longer accepts a `context` argument. If you have implemented this hook, you will need to remove the `context` argument from your implementation. If you need to access values computed by the view, you'll need to override the {attr}`~wagtail.snippets.views.snippets.SnippetViewSet.index_view_class` with a custom `IndexView` subclass. The `get_list_buttons` and `get_list_more_buttons` methods in particular may be overridden to customise the buttons on the listing.

Defining a function for this hook that accepts the `context` argument will raise a warning, and the function will receive an empty dictionary (`{}`) as the `context`. Support for defining the `context` argument will be completely removed in a future Wagtail release.

### Adoption of `classname` convention within the Image `Format` instance

When using `wagtail.images.formats.Format`, the created instance set the argument for classes to the attribute `classnames` (plural), this has now changed to `classname` (singular).

For any custom code that accessed or modified this undocumented attribute, updates will need to be made as follows.

Accessing `self.classnames` will still work until a future release, simply returning `self.classname`, but this will raise a deprecation warning.

```python
# image_formats.py
from django.utils.html import format_html
from wagtail.images.formats import Format, register_image_format


class CustomImageFormat(Format):

def image_to_html(self, image, alt_text, extra_attributes=None):
# contrived example - pull out the class and render on outside element
classname = self.classname # not self.classnames
self.classname = "" # not self.classnames
inner_html = super().image_to_html(image, alt_text, extra_attributes)
return format_html("<custom-image class='{}'>{}</custom-image>", classname, inner_html)


custom_format = CustomImageFormat('custom_example', 'Custom example', 'example-image object-fit', 'width-750')

register_image_format(custom_format)
```
21 changes: 16 additions & 5 deletions wagtail/images/formats.py
Original file line number Diff line number Diff line change
@@ -1,26 +1,37 @@
from warnings import warn

from django.utils.html import escape
from django.utils.translation import gettext_lazy as _

from wagtail.utils.apps import get_app_submodules
from wagtail.utils.deprecation import RemovedInWagtail60Warning

from .shortcuts import get_rendition_or_not_found


class Format:
def __init__(self, name, label, classnames, filter_spec):
def __init__(self, name, label, classname, filter_spec):
self.name = name
self.label = label
self.classnames = classnames
self.classname = classname
self.filter_spec = filter_spec
lb- marked this conversation as resolved.
Show resolved Hide resolved

def __str__(self):
return (
f'"{self.name}", "{self.label}", "{self.classnames}", "{self.filter_spec}"'
f'"{self.name}", "{self.label}", "{self.classname}", "{self.filter_spec}"'
)

def __repr__(self):
return f"Format({self})"

@property
def classnames(self):
warn(
"The class property `classnames` is deprecated - use `classname` instead.",
category=RemovedInWagtail60Warning,
)
return self.classname

def editor_attributes(self, image, alt_text):
"""
Return additional attributes to go on the HTML element
Expand All @@ -44,8 +55,8 @@ def image_to_html(self, image, alt_text, extra_attributes=None):
rendition = get_rendition_or_not_found(image, self.filter_spec)

extra_attributes["alt"] = escape(alt_text)
if self.classnames:
extra_attributes["class"] = "%s" % escape(self.classnames)
if self.classname:
extra_attributes["class"] = "%s" % escape(self.classname)

return rendition.img_tag(extra_attributes)

Expand Down
20 changes: 14 additions & 6 deletions wagtail/images/tests/tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
from wagtail.images.views.serve import ServeView
from wagtail.test.testapp.models import CustomImage, CustomImageFilePath
from wagtail.test.utils import WagtailTestUtils, disconnect_signal_receiver
from wagtail.utils.deprecation import RemovedInWagtail60Warning

from .utils import (
Image,
Expand Down Expand Up @@ -237,7 +238,7 @@ def test_rich_text_with_missing_image(self):
class TestFormat(WagtailTestUtils, TestCase):
def setUp(self):
# test format
self.format = Format("test name", "test label", "test classnames", "original")
self.format = Format("test name", "test label", "test is-primary", "original")
lb- marked this conversation as resolved.
Show resolved Hide resolved
# test image
self.image = Image.objects.create(
title="Test image",
Expand All @@ -260,7 +261,7 @@ def test_image_to_editor_html(self):
result = self.format.image_to_editor_html(self.image, "test alt text")
self.assertTagInHTML(
'<img data-embedtype="image" data-id="%d" data-format="test name" '
'data-alt="test alt text" class="test classnames" '
'data-alt="test alt text" class="test is-primary" '
'width="640" height="480" alt="test alt text" >' % self.image.pk,
result,
allow_extra_attrs=True,
Expand All @@ -272,26 +273,28 @@ def test_image_to_editor_html_with_quoting(self):
)
expected_html = (
'<img data-embedtype="image" data-id="%d" data-format="test name" '
'data-alt="Arthur &quot;two sheds&quot; Jackson" class="test classnames" '
'data-alt="Arthur &quot;two sheds&quot; Jackson" class="test is-primary" '
'width="640" height="480" alt="Arthur &quot;two sheds&quot; Jackson" >'
% self.image.pk
)
self.assertTagInHTML(expected_html, result, allow_extra_attrs=True)

def test_image_to_html_no_classnames(self):
self.format.classnames = None
self.format.classname = None
result = self.format.image_to_html(self.image, "test alt text")
self.assertTagInHTML(
'<img width="640" height="480" alt="test alt text">',
result,
allow_extra_attrs=True,
)
self.format.classnames = "test classnames"
self.format.classname = (
"test is-primary" # reset to original value for other tests
)

def test_image_to_html_with_quoting(self):
result = self.format.image_to_html(self.image, 'Arthur "two sheds" Jackson')
self.assertTagInHTML(
'<img class="test classnames" width="640" height="480" '
'<img class="test is-primary" width="640" height="480" '
'alt="Arthur &quot;two sheds&quot; Jackson">',
result,
allow_extra_attrs=True,
Expand All @@ -302,6 +305,11 @@ def test_get_image_format(self):
result = get_image_format("test name")
self.assertEqual(result, self.format)

def test_deprecated_classnames_property_access(self):
with self.assertWarns(RemovedInWagtail60Warning):
classname = self.format.classnames
self.assertEqual(classname, "test is-primary")


class TestSignatureGeneration(TestCase):
def test_signature_generation(self):
Expand Down
2 changes: 1 addition & 1 deletion wagtail/images/views/chooser.py
Original file line number Diff line number Diff line change
Expand Up @@ -277,7 +277,7 @@ def get_chosen_response_data(self, image):
{
"format": format.name,
"alt": alt_text,
"class": format.classnames,
"class": format.classname,
"html": format.image_to_editor_html(image, alt_text),
}
)
Expand Down