Skip to content

Commit fbcf2a4

Browse files
authored
feat: Add HTML class customization settings (#85)
* feat: Add `IMAGE_PROCESS_REMOVE_CLASS` setting, allowing the removal of `image-process-<transform>` CSS classes after image processing. These classes are user-assigned to trigger transformations, but once processed, they may no longer be needed. If enabled, the class is removed, and if it was the only class, the `class` attribute is deleted entirely. * refactor: Improve logic for handling class removal and prefixing - Rename `IMAGE_PROCESS_REMOVE_CLASS` to `IMAGE_PROCESS_ADD_CLASS` (default: `True`) - Introduce `IMAGE_PROCESS_CLASS_PREFIX` (default: `"image-process-"`) for class name customization - Update documentation to reflect these changes * chore: Add tests
1 parent c0c5853 commit fbcf2a4

File tree

3 files changed

+99
-8
lines changed

3 files changed

+99
-8
lines changed

README.md

Lines changed: 30 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,7 @@ Let's say you have defined the transformation described above. To get your
9595
image processed, it needs to have the right CSS class:
9696

9797
```html
98-
<img class="image-process-article-image" src="/images/pelican.jpg"/>
98+
<img class="image-process-article-image" src="/images/pelican.jpg" />
9999
```
100100

101101
This can be produced in Markdown with:
@@ -123,7 +123,6 @@ the `figure` directive:
123123
> dashes (`-`) in class names. To make sure everything runs
124124
> smoothly, do not use underscores in your transformation names.
125125
126-
127126
#### Responsive Images
128127

129128
You can use *Image Process* to automatically generate a set of
@@ -180,7 +179,7 @@ image from the original image (the original image is the value of the
180179
`src` attribute of the `<img>`). Image descriptions are hints
181180
about the resolution of the associated image and must have the suffix
182181
`x`. The `default` setting specifies the image to use to replace the `src`
183-
attribute of the image. This is the image that will be displayed by
182+
attribute of the image. This is the image that will be displayed by
184183
browsers that do not support the `srcset` syntax.
185184

186185
The `large-photo` transformation is an example of a transformation
@@ -194,7 +193,7 @@ the original image (the original image is the value of the `src`
194193
attribute of the `<img>`). Image descriptions are hints about the
195194
width in pixels of the associated image and must have the suffix
196195
`w`. The `default` setting specifies the image to use to replace the `src`
197-
attribute of the image. This is the image that will be displayed by
196+
attribute of the image. This is the image that will be displayed by
198197
browsers that do not support the `srcset` syntax.
199198

200199
In the two examples above, the `default` setting is a string referring to
@@ -210,7 +209,7 @@ image replacement case, described above.
210209
So, in HTML it should look like this:
211210

212211
```html
213-
<img class="image-process-large-photo" src="/images/pelican.jpg"/>
212+
<img class="image-process-large-photo" src="/images/pelican.jpg" />
214213
```
215214

216215
Which can be produced in Markdown with:
@@ -278,7 +277,7 @@ will be used to find the URL of the original image for this source in
278277
your article. The source may also have a `media`, which contains a
279278
rule used by the browser to select the active source. The `default`
280279
setting specifies the image to use to replace the `src` attribute of
281-
the `<img>` inside the `<picture>`. This is the image that will be
280+
the `<img>` inside the `<picture>`. This is the image that will be
282281
displayed by browsers that do not support the `<picture>` syntax. In
283282
this example, it will use the image `640w` from the source `default`.
284283
A list of operations could have been specified instead of `640w`.
@@ -481,7 +480,7 @@ IMAGE_PROCESS_ENCODING = "utf-8"
481480

482481
#### Copying EXIF Tags
483482

484-
You may ask _Image Process_ to copy the EXIF tags from your original image to
483+
You may ask *Image Process* to copy the EXIF tags from your original image to
485484
the transformed images. You must have [exiftool](https://exiftool.org/) installed.
486485

487486
```python
@@ -491,6 +490,30 @@ IMAGE_PROCESS_COPY_EXIF_TAGS = True
491490
Note that `exiftool` prior to version 12.46 cannot write WebP images, so if you work
492491
with WebP images, you should use version 12.46 or later.
493492

493+
#### Modifying the `class` Attribute of Processed Images
494+
495+
By default, *Image Process* adds the `image-process-<transform>`
496+
CSS class to transformed images. This behavior is controlled by the
497+
`IMAGE_PROCESS_ADD_CLASS` setting (default: `True`) and the
498+
`IMAGE_PROCESS_CLASS_PREFIX` setting (default: `"image-process-"`).
499+
500+
* If `IMAGE_PROCESS_ADD_CLASS` is `True`, the `<transform>` name is added
501+
to the `class` attribute of the image.
502+
You can customize the class prefix using `IMAGE_PROCESS_CLASS_PREFIX`.
503+
504+
* If `IMAGE_PROCESS_ADD_CLASS` is `False`, no class attribute will be added.
505+
506+
This setting allows you to control whether transformation details appear
507+
in the HTML output or to avoid conflicts with custom styles.
508+
509+
```python
510+
# Use a custom class prefix instead of "image-process-"
511+
IMAGE_PROCESS_CLASS_PREFIX = "custom-prefix-"
512+
513+
# Disable adding transformation class attributes
514+
IMAGE_PROCESS_ADD_CLASS = False
515+
```
516+
494517
## Known Issues
495518

496519
* Pillow, when resizing animated GIF files, [does not return an animated file](https://github.com/pelican-plugins/image-process/issues/11).
@@ -561,6 +584,5 @@ This project is licensed under the [AGPL-3.0 license](http://www.gnu.org/license
561584

562585
[Pelican image](https://web.archive.org/web/20090505115626/http://www.pdphoto.org/PictureDetail.php?mat=&pg=5726) in test data by Jon Sullivan. Published under a [Creative Commons Public Domain license](https://creativecommons.org/licenses/publicdomain/).
563586

564-
565587
[HTML5 responsive images]: https://www.smashingmagazine.com/2014/05/14/responsive-images-done-right-guide-picture-srcset/
566588
[BeautifulSoup documentation on parsers]: https://www.crummy.com/software/BeautifulSoup/bs4/doc/#installing-a-parser

pelican/plugins/image_process/image_process.py

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -314,6 +314,21 @@ def harvest_images_in_fragment(fragment, settings):
314314
for c in img["class"]:
315315
if c.startswith("image-process-"):
316316
derivative = c[14:]
317+
318+
# Determine whether to modify the class attribute.
319+
add_class = settings.get("IMAGE_PROCESS_ADD_CLASS", True)
320+
if not add_class:
321+
# Remove class if it's the only one, otherwise remove specific entry
322+
img["class"].remove(c)
323+
if len(img["class"]) == 0:
324+
del img["class"]
325+
else:
326+
class_prefix = settings.get(
327+
"IMAGE_PROCESS_CLASS_PREFIX", "image-process-"
328+
)
329+
if class_prefix != "image-process-":
330+
img["class"].remove(c)
331+
img["class"].append(f"{class_prefix}{derivative}")
317332
break
318333
else:
319334
continue

pelican/plugins/image_process/test_image_process.py

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -771,6 +771,60 @@ def test_try_open_image():
771771
assert not try_open_image(path.source)
772772

773773

774+
@pytest.mark.parametrize(
775+
"orig_tag, new_tag, setting_overrides",
776+
[
777+
(
778+
'<img class="image-process-crop" src="/tmp/test.jpg" />',
779+
'<img class="image-process-crop" src="/tmp/derivatives/crop/test.jpg"/>',
780+
[ # Default settings.
781+
{},
782+
{"IMAGE_PROCESS_ADD_CLASS": True},
783+
{"IMAGE_PROCESS_CLASS_PREFIX": "image-process-"},
784+
{
785+
"IMAGE_PROCESS_ADD_CLASS": True,
786+
"IMAGE_PROCESS_CLASS_PREFIX": "image-process-",
787+
},
788+
],
789+
),
790+
(
791+
'<img class="image-process-crop" src="/tmp/test.jpg" />',
792+
'<img class="custom-prefix-crop" src="/tmp/derivatives/crop/test.jpg"/>',
793+
[ # Custom class prefix.
794+
{"IMAGE_PROCESS_CLASS_PREFIX": "custom-prefix-"},
795+
{
796+
"IMAGE_PROCESS_ADD_CLASS": True,
797+
"IMAGE_PROCESS_CLASS_PREFIX": "custom-prefix-",
798+
},
799+
],
800+
),
801+
(
802+
'<img class="image-process-crop" src="/tmp/test.jpg" />',
803+
'<img class="crop" src="/tmp/derivatives/crop/test.jpg"/>',
804+
[ # Special case: empty string as class prefix.
805+
{"IMAGE_PROCESS_CLASS_PREFIX": ""},
806+
],
807+
),
808+
(
809+
'<img class="image-process-crop" src="/tmp/test.jpg" />',
810+
'<img src="/tmp/derivatives/crop/test.jpg"/>',
811+
[ # No class added.
812+
{"IMAGE_PROCESS_ADD_CLASS": False},
813+
{"IMAGE_PROCESS_ADD_CLASS": False, "IMAGE_PROCESS_CLASS_PREFIX": ""},
814+
],
815+
),
816+
],
817+
)
818+
def test_class_settings(mocker, orig_tag, new_tag, setting_overrides):
819+
"""Test the IMAGE_PROCESS_ADD_CLASS and IMAGE_PROCESS_CLASS_PREFIX settings."""
820+
# Silence image transforms.
821+
mocker.patch("pelican.plugins.image_process.image_process.process_image")
822+
823+
for override in setting_overrides:
824+
settings = get_settings(**override)
825+
assert harvest_images_in_fragment(orig_tag, settings) == new_tag
826+
827+
774828
def generate_test_images():
775829
settings = get_settings()
776830
image_count = 0

0 commit comments

Comments
 (0)