Image Handling Changes ‐ uuid5 file names and CSS url() - JimmXinu/FanFicFare GitHub Wiki

Image Handling Changes - uuid5 file names and CSS url()

Document uploaded January 2026 for testing version.

In pursuing support for image url() references in CSS, I've made some significant changes to FanFicFare's image handling and naming conventions.

Note: Unless you look inside the EPUB, or enable more CSS options, these changes should be invisible to the user.

FFF Including Images

  1. FFF can only include images in EPUB and HTML output formats.
  2. And only when include_images:true.
  3. By default, include_images is true only for EPUB in the Calibre FFF plugin.
  • From this point on, include_images:true and EPUB output are assumed.
  • By default, included images are processed by FFF to fit within a configurable maximum size and converted to jpg format. From this point on, all images will be assumed to be JPG format and name .jpg, but other formats are possible and supported, usually when using no_image_processing:true.

Cover Image

Cover images are special in several ways not deeply explored in this document. But it is notable that CSS url() images are deliberately excluded for make_firstimage_cover.

Image File Names

ffdl-0.jpg (Old)

In past, FFF renamed all included image to a basic pattern of images/ffdl-0.jpg where 0 is a simple incremental count.

The original image URL is moved to the longdesc attribute. On FFF update, the saved image URL in longdesc is used to match with <img> tags in other chapters in case of the same image appearing more than once.

For Example:

<img src="http://i.imgur.com/bo8eD.png">

Becomes:

<img longdesc="http://i.imgur.com/bo8eD.png" src="images/ffdl-5.jpg">
  • The prefix ffdl- represents the older name of FFF, FanFictionDownLoader and, being purely internal, has never been changed for reasons of nostalgia.
  • The longdesc attribute is used (arguably abused) because it doesn't trigger epubcheck errors and isn't generally discarded by other epub tools.
  • The original image URLs are not used for image file names because of both excessive length in some image URLs, and common image names being reused by different images.

ffdl-04402fe1-e695-520e-b28b-2d4898a9453c.jpg (New)

Now, image files are named using the uuid5 value for the original image URL instead of a counter. uuid5 is based on one-way cryptographic hashing, but will always be the same for a given URL.

While we can't get the original image URL back, we don't need to--we want to map from URL to image.

For Example:

<img src="http://i.imgur.com/bo8eD.png">

Becomes:

<img longdesc="http://i.imgur.com/bo8eD.png" src="images/ffdl-04402fe1-e695-520e-b28b-2d4898a9453c.jpg">
  • uuid5 generates values within a 'namespace', itself a uuid value. I've hardcoded a randomly generated uuid for the namespace. So even for different users on different computers, FFF will generate the same image file name for the same image URL.
  • The primary reason for this change is to allow for CSS url() image references where there is no easy equivalent of longdesc to store the original image URL.
  • A minor additional benefit is that an image's name within the EPUB will no longer change if more images are before it. IE, 'ffdl-1.jpg' becoming ffdl-2.jpg if a new chapter containing an image is added before it.

CSS url()

CSS allows for images (usually for background-image) to be specified using url(imgurl). In past, FFF has largely ignored these (see additional_images below for the exception).

Now, FFF scans the generated CSS stylesheet, and all chapter texts for embedded <style> tags and inline <tag style="..."> attributes for url() constructs, extracts the image URL, renames it, and includes the image.

For Example:

<style>
.loremipsum { background-image: url("https://picsum.photos/2000/1500") }
</style>

becomes:

<style>
.loremipsum { background-image: url("images/ffdl-980adf93-a1b4-56d2-9b35-8c560e4256cd.jpg") }
</style>

And

<p  style="background-image: url('https://picsum.photos/20/10')">Lorem...

becomes:

<p  style="background-image: url('images/ffdl-2c2f5983-f722-5345-ab91-85ec2a4b345e.jpg')">Lorem...
  • CSS url() references are all assumed to be images by FFF.
  • FFF does not try to make sure the url() using CSS rules are actually used. (With one exception, see style="..." attribute below.)
  • Embedded <style> tags and inline <tag style="..."> attributes are only consider within chapter texts. Not anywhere else on the site page, or in FFF's titlepage, logpage, etc.
  • When include_images:false, FFF's normal processing removes <img> tags. CSS url() references are not removed, nor are they changed. They are left as-is.

Getting CSS Included in EPUB

How does CSS get into your EPUB? There are four different places CSS can come from in FFF ebooks. Spoiler: Only one of them is used by default.

Why is most CSS off by default? FFF was built to intentionally normalize stories to all have the same appearance regardless of site or author.

output_css

The primary CSS for FFF is from the output_css INI setting. This is the only CSS included by FFF by default. The default output_css varies slightly by EPUB vs HTML and depending on the site. You may change output_css or add to it in your personal.ini.

  • output_css ends up in a separate stylesheet.css file inside the EPUB which is included in all chapter files.

OTW(AO3) use_workskin

OTW sites allow authors to specify additional CSS for stories using 'workskins'. This is off by default, but can be enabled by site or story in your personal.ini.

  • This is currently only implemented for OTW sites such as AO3.
  • Workskin CSS is appended to output_css in a stylesheet.css file inside the EPUB which is included in all chapter files.

Embedded <style> Tags

Depending on the site, authors (or sites) can embed <style> tags directly in chapter text. By default, <style> tags are discarded by FFF. That's controlled by FFF's remove_tags setting, so to keep <style> tags, you have to remove style from remove_tags.

For Example:

[defaults]
remove_tags:script
  • NOTE This only covers <style> tags directly in chapter text. It does not cover other <style> tags the site may put in the same page as the chapter text.

Inline <tag style="..." Attributes

More commonly seen than <style> tags, are style attributes on other tags that then apply to that tag and it's contents. These are very common on some sites, such as the Xenforo forum sites. By default, style attributes are discarded by FFF. That's controlled by FFF's keep_html_attrs setting that you have to add style to.

For Example:

[defaults]
add_to_keep_html_attrs:,style
  • Yes, it's a nuisance that tag and attributes are treated differently. They were implemented at different times and I am extremely adverse to changes that break back compatibility of people's existing INI.
  • A special exception to the doesn't check if CSS is used rule is that a tag with style="..." attributes does not have url() image processing done if the tag is empty. This was added to deal with pre-existing failed XF2 embedded videos that brought in images that then couldn't be seen. It may need changing in future.

    Example: <span style="background:url(https://i.ytimg.com/vi/JDLFbGU2vhg/hqdefault.jpg) 50% 50% / cover"></span>

Image Download Failures

When an image download fails, in past, FanFicFare would keep the <img> tag, but set both the src and longdesc attributes to failedtoload. Eg: <img longdesc='failedtoload' src='failedtoload' />

This had two effects:

  1. The image in the epub is definitely broken. Your reader won't spend time and effort trying to download it.
  2. FFF knows not to try that image again on update.

The downside was that the original URL was lost and could only be recovered by forceably re-downloading the chapter or story.

Retaining Original URLs

Now, FFF will prepend failedtoload (note there's a space) to the image URL.

For example:

<img src="http://i.imgur.com/nosuch.png">

Becomes:

<img src="failedtoload http://i.imgur.com/bo8eD.png">

And in CSS:

.loremipsum { background-image: url("https://nosuch.site/ancient.gif") }

Becomes:

.loremipsum { background-image: url("failedtoload https://nosuch.site/ancient.gif") }
  1. The image is still definitely broken in epub, and FFF still knows it. longdesc is not set for <img> failures.
  2. However, now the user could manually delete the leading failedtoload (including the space) from image URL(s) and FFF would try those images again during the next update.

XF2 New Setting link_embedded_media

This is only somewhat related to the image handling changes above. While testing CSS url() inclusion I found I had a bunch of stories from XF2 sites (SB/SV/QQ/etc) with inline style="background-image:url(...)" tags for embedded YouTube videos that came out empty. Because they were consistent across several high traffic sites, I deemed it worth special code.

To better handle embedded YouTube videos, I've added code to recognize them and change them to an image of the thumbnail linked to the video on YouTube. This option is on by default.

## Recognize 'data-s9e-mediaembed' embedded media with CSS background
## and modify to be an <a> tag linking to the video around an <img>
## tag of the CSS background image.  Only seen with YouTube so far.
## On by default.
#link_embedded_media:true
  • No, I do not consider it practical to try and actually embed a video player. The HTML served by XF2 doesn't have it either--it's generated by Javascript in the browser.

Other Details

A few other details and changes made along the way:

'Pretty Print' EPUB XML Meta Files

FFF's EPUB XML meta files (content.opf, toc.ncx, container.xml) now have whitespace and 'pretty' formatting. I vaguely remember rejecting requests to do that before because of problem with how toc.ncx chapter titles came out. But I don't see those problems now and EpubMerge has used toprettyxml() for a while now.

webp Image Type

FFF now recognizes and correctly types webp images as mimetype image/webp. Probably doesn't matter much--every viewer I've used ignores mimetype and file extension of image when they are wrong.

Existing Images Not Reprocessed

In past, as part of updating an EPUB, even previously downloaded images would be processed again (applying max size, jpg conversion). In most cases it didn't matter.

Now, previously downloaded images in the EPUB will be re-used as-is.

Deleted Chapters Can Reuse Images on Update

In past, <img longdesc="imgurl"... in chapter text was the only mapping from image URL to ffdl-1.jpg image file in EPUB. So if the chapter containing that <img> tag was deleted, the image would be discarded and downloaded again (assuming it's needed). This is a little easier than deleting the <meta name="chapterurl" line from each chapter to re-download.

Now, because we can map image URL to ffdl-[uuid5].jpg image file, it's practical to force the update of specific chapters by deleting from the EPUB and still reuse previously downloaded images.

additional_images Images and Matching CSS Not Changed.

Before these changes, a workaround method to include CSS url() images in an EPUB was formulated: the additional_images setting.

To maintain backward compatibility, any image in additional_images will not be changed in CSS url(), regardless of where it appears.

For Example:

additional_images:file:///C:/Users/user/Desktop/nook/background.jpeg

And in output_css:

body { 
 background-image:images/background.jpeg
}

@import url() Not Supported

This is the only use of CSS url() I know of off hand that isn't an image. As far as I know, it's only valid in a stylesheet file, not embedded or inline. So don't put it in output_css.

⚠️ **GitHub.com Fallback** ⚠️