diff --git a/CHANGELOG.txt b/CHANGELOG.txt
index 4bac0537307..42218602f73 100644
--- a/CHANGELOG.txt
+++ b/CHANGELOG.txt
@@ -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)
diff --git a/docs/advanced_topics/customisation/page_editing_interface.md b/docs/advanced_topics/customisation/page_editing_interface.md
index dd58caf6fc1..2df9461115e 100644
--- a/docs/advanced_topics/customisation/page_editing_interface.md
+++ b/docs/advanced_topics/customisation/page_editing_interface.md
@@ -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 `
` tag.
```{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`**
diff --git a/docs/advanced_topics/images/changing_rich_text_representation.md b/docs/advanced_topics/images/changing_rich_text_representation.md
index c575730f993..f52a1b51913 100644
--- a/docs/advanced_topics/images/changing_rich_text_representation.md
+++ b/docs/advanced_topics/images/changing_rich_text_representation.md
@@ -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)
)
```
diff --git a/docs/releases/5.2.md b/docs/releases/5.2.md
index 45f77f40853..e5d239bfa3f 100644
--- a/docs/releases/5.2.md
+++ b/docs/releases/5.2.md
@@ -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)
@@ -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("{}", classname, inner_html)
+
+
+custom_format = CustomImageFormat('custom_example', 'Custom example', 'example-image object-fit', 'width-750')
+
+register_image_format(custom_format)
+```
diff --git a/wagtail/images/formats.py b/wagtail/images/formats.py
index e133fb17e3c..3e2bd66ff87 100644
--- a/wagtail/images/formats.py
+++ b/wagtail/images/formats.py
@@ -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
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
@@ -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)
diff --git a/wagtail/images/tests/tests.py b/wagtail/images/tests/tests.py
index 79a0e660af1..f5df41f5131 100644
--- a/wagtail/images/tests/tests.py
+++ b/wagtail/images/tests/tests.py
@@ -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,
@@ -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")
# test image
self.image = Image.objects.create(
title="Test image",
@@ -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(
'
' % self.image.pk,
result,
allow_extra_attrs=True,
@@ -272,26 +273,28 @@ def test_image_to_editor_html_with_quoting(self):
)
expected_html = (
'
'
% 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(
'
',
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(
- '
',
result,
allow_extra_attrs=True,
@@ -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):
diff --git a/wagtail/images/views/chooser.py b/wagtail/images/views/chooser.py
index f247cb2b3b5..ce1792f4404 100644
--- a/wagtail/images/views/chooser.py
+++ b/wagtail/images/views/chooser.py
@@ -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),
}
)