Code:
# FanFicFare Configuration File - Optimized for AO3 & Calibre Integration
# ================================================
# ================================================[defaults]
# ============================================================================
# BASIC SETTINGS & FORMATTING
# ============================================================================
# HTML processing options
replace_xbr_with_hr:3
replace_hr:false
replace_br_with_p:false
slow_down_sleep_time:0.5
# Date formatting (http://docs.python.org/library/datet...ptime-behavior)
datePublished_format:%%B %%d, %%Y
dateUpdated_format:%%B %%d, %%Y
include_subject_tags:filtered_freeform_tags,freeformtags
include_in_genre:genre,forumtags,freeformtags,ao3categories
# include_subject_tags should have values if you want to put tags in Calibre.
#If you don't want to use the prefix_* tags you can remove those lines entirely
# and add the tags you want in include_subject_tags.
# ============================================================================
# CUSTOM FIELD DEFINITIONS
# ============================================================================
# Define all custom metadata fields we'll create from AO3 data
add_to_extra_valid_entries:,additional_characters,category_main,dateRange,icon_bookmarked,icon_subscribed,icons,prefix_category,prefix_rating,prefix_ships,prefix_status,prefix_wordcount,fanfic_rating,fanfic_status,filtered_freeform_tags
# Labels for custom fields (how they appear in Calibre)
additional_characters_label:Characters
category_label:Fandom
category_main_label:Fandom
dateRange_label:Date Range
filtered_freeform_tags_label:Genre Tags
ship_label: Ships
freeformtags_label:Freeform Tags
# Define what source data goes into each custom field
include_in_additional_characters: characters
include_in_category_main: category
include_in_dateRange: datePublished,dateUpdated
include_in_icons: icon_bookmarked,icon_subscribed
include_in_prefix_category: category
include_in_prefix_rating: rating
include_in_prefix_ships: ships
include_in_prefix_status: status
include_in_prefix_wordcount: numWords
include_in_filtered_freeform_tags: freeformtags
# Preserve order of items in lists (important for consistency)
keep_in_order_category:true
keep_in_order_characters:true
keep_in_order_ships:true
keep_in_order_additional_characters:true
keep_in_order_category_main:true
keep_in_order_dateRange:true
keep_in_order_icons:true
keep_in_order_prefix_category:true
keep_in_order_prefix_ships:true
keep_in_order_filtered_freeform_tags:true
# ============================================================================
# METADATA FILTERING & EXCLUSIONS
# ============================================================================
exclude_metadata_pre:
# Remove redundant fandom suffixes
category=~(.*) - Fandom
# Filter out generic/useless character entries
additional_characters==Other(s)
additional_characters=~(Original|Various) Character\(?s?\)?
# Remove generic placeholder tags
freeformtags,genre==Other Additional Tags to Be Added
warnings==Creator Chose Not To Use Archive Warnings
warnings==No Archive Warnings Apply
# Ship filtering - remove non-relationship entries
ships,prefix_ships!~(.*)(\/| & )(.*) # Must contain / or &
ships,prefix_ships=~(.*) & (.*) # Remove platonic relationships
prefix_ships=~^(.*)\(?(implied|mentioned)\)? # Remove implied/mentioned ships
# ============================================================================
# METADATA TRANSFORMATIONS & REPLACEMENTS
# ============================================================================
replace_metadata:
# Rating standardization
rating=> Audiences=>
rating=>Teen [Aa]nd Up=>Teen
# Relationship processing
ships=>(.*)[/](.*) \(?[Ff]riendship(?: only)\)?=>\1 & \2
# Fandom cleaning
category,prefix_category=>No Fandom=>Original Work
category,prefix_category=> \(?(- All Media Types|- Fandom|Movies|Movie [0-9]+|Comics|TV|Video Games?)\)?$=>
# Character name cleaning
additional_characters=> - Character=>
additional_characters=> ?\((cameo|briefly|if you squint|sort of)\)=>
additional_characters=> \([Cc]haracter\)=>
additional_characters=>\(mentions of\) =>
# Ship name cleaning
category,ships= - Fandom$=>
ships=> - Relationship=>
ships=>^(.* - Relationship)$=>
ships=>^(Eventual (.*)/(.*))$=>
# Extract first item for prefixed tags (for Calibre tag system)
prefix_category_LIST=>^(.*?)(\,.*)=>\1
category_main_LIST=>^(.*?)(\,.*)=>\1
prefix_ships_LIST=>^(.*?)(\,.*)=>\1
# Add prefixes to tags for better sorting in Calibre
prefix_ships=>^(.*)=>[p] \1
prefix_category=>^(.*)=>[c] \1
prefix_rating=>^(.*)=>[r] \1
prefix_status=>^(.*)=>[s] \1
# Word count grouping (creates ranges for better filtering)
prefix_wordcount=>^(\d+|([0-4],\d{3})*|5,000)$=>[w] 0 - 5000
prefix_wordcount=>^((?!5,000)([5-9],\d{3})*|10,000)$=>[w] 5001 - 10000
prefix_wordcount=>^((?!10,000)(1\d,\d{3})*|20,000)$=>[w] 10001 - 20000
prefix_wordcount=>^((?!20,000)([2-3]\d,\d{3})*|40,000)$=>[w] 20001 - 40000
prefix_wordcount=>^((?!40,000)([4-7]\d,\d{3})*|80,000)$=>[w] 40001 - 80000
prefix_wordcount=>^((?!80,000)(([8-9]\d)|(\d{3,}))(,\d{3})+)$=>[w] 80000+
# Date range formatting (combines publish/update dates intelligently)
dateRange_LIST=>([^\s]+)\s+(\d{1,2})\,\s+(\d{4})\,\s([^\s]+)\s+(\d{1,2})\,\s+(\d{4})=>\1 \2, \3-\4 \5, \6 # Different dates
dateRange_LIST=>([^\s]+)\s+(\d{1,2})\,\s+(\d{4})-([^\s]+)\s+(\d{1,2})\,\s+\3=>\1 \2-\4 \5, \3 # Same year
dateRange_LIST=>([^\s]+)\s+(\d{1,2})-\1\s+(\d{1,2})\,\s+(\d{4})=>\1 \2-\3, \4 # Same month
# Bookmark/subscription status icons
icon_bookmarked=>True=>Bookmarked
icon_subscribed=>True=>Subscribed
icon_bookmarked=>False=>Not Bookmarked
icon_subscribed=>False=>Not Subscribed
# Icon combinations for visual indicators
icons_LIST=>^(Bookmarked\, Subscribed)$=>⭐📖 # Both
icons_LIST=>^(Not Bookmarked\, Not Subscribed)$=>◈ # Neither
icons_LIST=>^(Not Bookmarked\, Subscribed)$=>📖 # Subscribed only
icons_LIST=>^(Bookmarked\, Not Subscribed)$=>⭐ # Bookmarked only
# Dynamic CSS color coding based on rating
output_css=>fff_titlepage_color_replace=>264701&&rating==General # Green
output_css=>fff_titlepage_color_replace=>38419D&&rating==Teen # Blue
output_css=>fff_titlepage_color_replace=>66347F&&rating==Mature # Purple
output_css=>fff_titlepage_color_replace=>8F0101&&rating==Explicit # Red
output_css=>fff_titlepage_color_replace=>1B1B1B&&rating==Not Rated # Black
output_css=>fff_titlepage_color_replace=>555555 # Default gray
# ============================================================================
# GENRE TAG FILTERING (CALIBRE TAGS)
# ============================================================================
# Only allow specific genre tags into Calibre's main tag system
# This prevents tag spam while keeping useful categorization
#
# To add new allowed genres: Add a line like "filtered_freeform_tags!=Your Tag"
# To remove genres: Delete the line or comment it out with ##
# Whitelist using a single regex: keep only tags that MATCH this list
# (everything else is excluded). Edit this list to add/remove allowed tags.
filtered_freeform_tags!~^(Angst|Fluff|Domestic Fluff|Smut|Light-Hearted|Happy Ending|Crack|Dead Dove: Do Not Eat|Family|Found Family|Friendship|Childhood Friends|Sibling Bonding|Batfamily|Friends to Lovers|Enemies to Friends|Enemies to Lovers|Enemies|Pining|Mutual Pining|Hurt|Hurt\/Comfort|Emotional Hurt\/Comfort|Implied\/Referenced Character Death|One Shot|Drabble|5 Things|5\+1 Things|Slice of Life|Slow Build|Slow Burn|Alternate Universe|Alternate Universe - Modern Setting|Modern Era|Canon Universe|Canon Related|Not Canon Compliant|NCC|Domestic|Out of Character|OOC|Non-Sexual|Image|DCU \(Comics\)|DCEU|Young Justice|Batman \(Comics\)|Batman - All Media Types|Justice League - All Media Types|Justice League \(DCU\))$
# filtered_freeform_tags!~^Angst
# filtered_freeform_tags!=Fluff
# filtered_freeform_tags!=Smut
# filtered_freeform_tags!=Crack
filtered_freeform_tags!=HumorZ
# Allow all "AU - ..." variants
filtered_freeform_tags!~^AU -.*
# ============================================================================
# CALIBRE CUSTOM COLUMNS MAPPING
# ============================================================================
# Maps processed metadata to specific custom columns in Calibre
# These column names must match what you've set up in Calibre's preferences
add_to_custom_columns_settings:
additional_characters=>#character # Characters column
category_main=>#fandom # Fandom column
rating=>#audience # Audience/Rating column
ships=>#ship # Relationships column
chapterslashtotal=>#chapter_count # Chapter count column
dateRange=>#date_range # Date range column
freeformtags=>#additional_tags # All original tags column
filtered_freeform_tags=>#genre_tags # Filtered genre tags column
bookmarked=>#work_bookmarked # Bookmark status column
subscribed=>#work_subscribed # Subscription status column
fanfic_rating=>#fanfic_rating # Original rating column
fanfic_status=>#fanfic_status # Work status column
kudos=>#kudos # Kudos from AO3
# ============================================================================
# CALIBRE TAG SYSTEM INTEGRATION
# ============================================================================
# Controls what appears in Calibre's main tag browser for sorting/filtering
include_subject_tags:prefix_ships_LIST,prefix_category_LIST,prefix_rating,prefix_status,prefix_wordcount,filtered_freeform_tags
# ============================================================================
# VISUAL STYLING (CSS)
# ============================================================================
# Custom CSS for enhanced book covers and reading experience
add_to_output_css:
/* Base typography */
body {
font-family: 'Noto Sans', sans-serif;
}
/* Title page styling with dynamic colors */
body.fff_titlepage {
font-size: 2.5vmax;
font-family: 'Roboto', sans-serif;
background-color: #fff_titlepage_color_replace;
color: white;
}
/* Horizontal rules */
hr {
display: block;
border: 0;
border-top: 1px solid;
padding: 0;
}
/* Flexbox layout for decorative elements */
.flex-parent {
display: flex;
align-items: center;
}
.flex-child-edge {
flex-grow: 2;
border-bottom: 1px solid;
}
.flex-child-text {
flex-basis: auto;
flex-grow: 0;
text-align: center;
margin: 0 5px 0 5px;
font-family: 'Roboto', sans-serif;
}
.flex-child-text.stats span { font-weight: bold; }
.flex-child-text.category { font-weight: bold; }
/* Title styling */
.fff_titlepage .title h1 {
font-family: 'Roboto', sans-serif;
font-size: 3vmax;
margin: 0;
font-weight: normal;
}
.fff_titlepage .title h1 a { font-weight: bold; }
/* Link styling */
.fff_titlepage .title a,
.fff_titlepage .tags a,
.fff_titlepage .tag-summary-content a {
text-decoration: none;
color: unset;
}
.fff_titlepage .tag-summary-content a {
font-style: italic;
}
/* Content styling */
.fff_titlepage .tag-summary-content p {
margin-top: 0;
}
.fff_titlepage .tags {
display: block;
padding: 0;
}
/* Definition list styling */
dl .inline dt:after { content:'\00a0'; }
dl .inline dt { float: left; }
.fff_titlepage dt { font-family: 'Roboto Condensed'; }
.fff_titlepage dd { margin-left: 0.75em; }
.fff_titlepage dl, .fff_titlepage dt { margin: 0; }
/* Responsive design for different screen sizes */
.display-on-reader { display: none; }
@media only screen and (max-device-width: 480px),
only screen and (min-device-width: 768px) and (max-device-width: 1024px) {
body.fff_titlepage, .fff_titlepage dt {
background_color: unset;
color: unset;
font-family: unset;
}
.display-on-cover { display: none; }
.display-on-reader { display: block; }
.flex-parent.display-on-reader { display: flex; }
}
# ============================================================================
# TITLE PAGE TEMPLATE
# ============================================================================
# HTML template for the book's title page
titlepage_start: <?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>${title} by ${author}</title>
<link href="stylesheet.css" type="text/css" charset="UTF-8" rel="stylesheet"/>
<meta name="calibre-html-render-data"/>
</head>
<body class="fff_titlepage">
<div class="title">
<h1><a href="${storyUrl}">${title}</a> by ${authorHTML}</h1>
</div>
<div class="flex-parent display-on-reader">
<div class="flex-child-edge"></div>
<div class="flex-child-text">◈</div>
<div class="flex-child-edge"></div>
</div>
<div class="flex-parent display-on-cover">
<div class="flex-child-edge"></div>
<div class="flex-child-text category">${category_main}</div>
<div class="flex-child-edge"></div>
</div>
<dl class="tags">
# Individual metadata entry template
titlepage_entry:
<dt><b>${label}:</b></dt> <dd>${value}</dd>
# Wide entry template (unused in this config)
titlepage_wide_entry:
# Entries that should span full width (unused in this config)
wide_titlepage_entries:
# Entry template for items without labels
titlepage_no_title_entry: ${value}<br />
# End of title page template
titlepage_end:
</dl>
<div class="flex-parent display-on-cover">
<div class="flex-child-edge"></div>
<div class="flex-child-text stats"><span>${rating}</span> ${icons} ${numWords} ◈ ${chapterslashtotal}</div>
<div class="flex-child-edge"></div>
</div>
<div class="flex-parent display-on-reader">
<div class="flex-child-edge"></div>
<div class="flex-child-text">${icons}</div>
<div class="flex-child-edge"></div>
</div>
<div class="tag-summary-content">${description}</div>
</body>
</html>
# ============================================================================
# EPUB SETTINGS
# ============================================================================
[epub]
make_firstimage_cover:false
jpg_quality:100
convert_images_to:png
remove_transparency:false
no_image_processing:true
# ============================================================================
# ARCHIVE OF OUR OWN (AO3) SPECIFIC SETTINGS
# ============================================================================
[archiveofourown.org]
# Authentication settings
is_adult:false
always_login:false
#always_login:true
#slow_down_sleep_time:4
# Replace with your credentials (or leave as XXXXXXXX for manual login)
# username:XXXXXXXX
# password:XXXXXXXX
# Chapter handling
add_chapter_numbers:toconly
mark_new_chapters:latestonly
# Chapter title patterns
chapter_title_def_pattern: ${title}
chapter_title_add_pattern: ${title} (${date})
chapter_title_new_pattern: ${title} (${date}) | NEW
chapter_title_addnew_pattern: ${title} (${date}) | NEW
# AO3-specific field mappings
include_in_genre:
include_in_icon_bookmarked: bookmarked
include_in_icon_subscribed: subscribed
# Preserve AO3 tag order
keep_in_order_ao3categories:true
keep_in_order_freeformtags:true
# AO3-specific labels
# chapterslashtotal_label:Chapters
freeformtags_label:Tags
#freefromtags_label:Tags
# ao3categories_label:Category
# ============================================================================
# FREEFORM TAG PROCESSING
# ============================================================================
# Clean up and normalize commonly used tags before filtering
replace_metadata:
# Normalize compound tags
freeformtags=>^(Angst and )(.*)=>Angst\,\2
freeformtags=>^(Fluff and )(.*)=>Fluff\,\2
freeformtags=>^(Smut and )(.*)=>Smut\,\2
# Simplify redundant modifiers
freeformtags=>(\w+ )(Fluff)$=>Fluff
freeformtags=>(\w+ )(Smut)$=>Smut
freeformtags=>(\w+ )(Angst)$=>Angst
freeformtags=>(.*)(Hurt\/Comfort)$=>Hurt/Comfort
freeformtags=>^(Hurt)(?: .*)?$=>Hurt
# AU tag standardization
freeformtags=>^(Alternate Universe)$=>
freeformtags=>^(Alternate Universe -)=>AU -
# Remove overly generic tags
freeformtags=>^(Drama & Romance)$=>Drama\,Romance
freeformtags=>^(Friendship)$=>
freeformtags=>^(Friendship/Love)$=>
freeformtags=>^(Male-Female Friendship)$=>
freeformtags=>^(Platonic Female/Male Relationships)$=>
freeformtags=>^(Platonic Relationships)$=>
# Standardize common variants
freeformtags=>^(Canon Divergent)$=>Canon Divergence
freeformtags=>^[Ll]ighthearted$=>Light-Hearted
freeformtags=>^[Bb]atfam$=>Batfamily
# Additional tag processing
extratags:
# Author URL cleaning (handle orphaned accounts)
add_to_replace_metadata:
authorUrl=>(/users/orphan_account)/pseuds/.*$=>\1
# Title page content order
titlepage_entries: <div class="inline">,<div class="display-on-reader">,category,</div>,seriesHTML,warnings,ships,additional_characters,freeformtags,dateRange,<div class="display-on-reader">,rating,chapterslashtotal,numWords,</div>,</div>
# ============================================================================
# CHAPTER TEMPLATE
# ============================================================================
chapter_start: <?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>${chapter}</title>
<link href="stylesheet.css" type="text/css" charset="UTF-8" rel="stylesheet"/>
<meta name="chapterurl" content="${url}"></meta>
<meta name="chapterorigtitle" content="${origchapter}"></meta>
<meta name="chaptertoctitle" content="${tocchapter}"></meta>
<meta name="chaptertitle" content="${chapter}"></meta>
</head>
<body class="fff_chapter">
<h3 class="fff_chapter_title">${origchapter}<hr><small>${date}</small></h3>
# ================================================
# END OF CONFIGURATION
# ================================================