Releases: rupor-github/fb2cng
v1.1.8
Work around
KP3/KFX has rendering issues where dropcaps combined with negative left margins misplace surrounding text.
For affected KFX paragraphs only, insert a narrow no-break spacer after the first dropcap rune and keep it inside the dropcap span. This does not fully resolve the issue, but makes rendering somewhat better visually.
Full Changelog: v1.1.7...v1.1.8
v1.1.7
New features
Allow negative margins through KFX pipeline
- Removed negative margin clamping from CSS converter; values now pass
through the entire pipeline to the final output - Fixed filterTagDefaultsIfInherited to filter any tag-default margin
(not just zero) when inherited container margin is non-zero, preventing
tag-level negative margins from overriding accumulated container margins
(e.g., poem 3em + verse 2em = 5em was being replaced by p's -0.533em) - Updated tests: TestNegativeMarginPassthrough, added tests for tag-default
filtering and negative margin preservation at output
Note: custom CSS with negative horizontal margins on p elements may cause visual artifacts on
Kindle due to renderer behavior. The default CSS is not affected.
Full Changelog: v1.1.6...v1.1.7
v1.1.6
New features
- Use em units for text-indent and horizontal spacing in KFX output
Previously, CSS em values for text-indent, margin-left/right, and
padding-left/right were converted to % using fixed ratios (1em = 3.125%
for text-indent, 1em = 6.25% for horizontal margins). This made indents and
margins viewport-relative — they stayed at a fixed fraction of screen width
regardless of the user's font size setting in the Kindle viewer.
Now em values are preserved as em in KFX output, so indentation and
horizontal spacing scale proportionally when the user changes font size. This
matches KP3 (Kindle Previewer 3) and the Amazon backend conversion pipeline.
Full Changelog: v1.1.5...v1.1.6
v1.1.5
Bug Fixes
- Fix EPUB page map producing only synthetic pages (cover/TOC/annotation): each new XHTML file produced by section splitting now registers a page entry in the page map
- Changed minimal supported screen dimensions to 400x600
Full Changelog: v1.1.4...v1.1.5
v1.1.4
Bug fixes
- Fix KFX footnote backlink navigation landing before the reference
- Debug report MANIFEST now lists all files in the archive
Full Changelog: v1.1.3...v1.1.4
v1.1.3
Bug fixes
- Fix body-level images and body-level title inline images not being indexed as referenced, causing them to be excluded during conversion
- Fix
kfxgen.pidMapWithOffsetformat capability being incorrectly declared for books with image-only inline entries (no mixed text+image content), which produced KFXInput validation error - Fix mojibake when FB2 file declares non-UTF-8 encoding but content is actually UTF-8
- Fix element ordering in EPUB and KFX generators to match FictionBook.xsd schema
- EPUB: body-level image now correctly precedes body title (was emitted after title and epigraphs)
- KFX: section-level image now correctly follows title and epigraphs (was emitted before title); section epigraphs now correctly follow title (were emitted after annotation)
- Split body image into separate KFX storyline when CSS requests page break.
Full Changelog: v1.1.2...v1.1.3
v1.1.2
Bug fixes
- Removed hardcoded registration of
footnote>pdescendant selector that unconditionally overrode user CSS. Footnote paragraph styling is now handled entirely through the CSS cascade. - Fixed missing
position:footer/yj.classification:footnotemarkers on footnote body paragraphs. - Fixed CSS descendant selector matching during deferred style resolution.
- Fixed "more" indicator placement in footnotes with epigraphs/annotations (Affected formats: KFX (azw8) and EPUB3 in float footnote mode).
- Container-set CSS properties are not overridden by tag defaults any more
Full Changelog: v1.1.1...v1.1.2
v1.1.1
Maintenance release - use latest gencfg package.
No functional changes
Full Changelog: v1.1.0...v1.1.1
v1.1.0
New features
- added --asin flag to be able to set ASIN during conversion if necessary
Bug Fixes
Critical
- Fixed hyphenation for non-ASCII languages (Cyrillic, Greek, etc.) — byte/rune index confusion caused pattern weights to be silently lost
- Fixed race condition on global
slug.Lowercasein concurrent transliteration calls
High
SecretStringno longer leaks secrets viafmt.Sprintf/%v— addedString()andGoString()methods- CSS
url()resolution now usesos.DirFSto prevent arbitrary file reads via path traversal - Added 256 MB limit on base64 binary decoding to prevent OOM from malicious FB2 files
- Added 8192x8192 dimension cap on SVG rasterization to prevent OOM
- Fixed infinite loop in JPEG quality detection on crafted input
- Fixed JPEG SOI header validation (
&&→||) — single-byte corruption no longer passes
Medium
- Added Zip Slip protection in archive walker — rejects entries with
../or absolute paths - Fixed temp directory leak in
Prepare()on both error and success paths - Fixed off-by-one in
trie.allSubstrings()— now matchesallSubstringsAndValues()behavior - Fixed CSS injection — selector and
url()values are now properly escaped - Fixed
parseDimension— rewritten to correctly reject malformed CSS dimensions - Eliminated stale
Imports/FontFacessync bug by replacing fields with methods - Removed dead code in
indexHref— replacedurl.Parse()with explicit scheme allowlist encodeImagenow returns an error for unsupported formats instead of silentnil, nil- Fixed
Report.Close()— botharc.Close()andr.file.Close()errors are now reported viaerrors.Join - Fixed
%v→%win error wrapping inconfig.Dump() - Fixed case-sensitivity mismatch in MHL connector — target is now normalized to lowercase
- Fixed
isTitleEmpty— now recurses into child segments viaAsPlainText()
Performance
- Replaced
+=string concatenation withstrings.Builderin hot hyphenation loops - Cached HTML entities JSON parsing with
sync.Once— no longer re-parsed on everyPrepare() - Moved
isKnownTextTagmap to package level — no longer allocated per call - Fixed O(n²)
AsTOCText— trackslastByteinstead of callingbuf.String()in loop - Replaced
strings.NewReader(string(bytes))withbytes.NewReaderto avoid copy - Converted recursive
parseDescendantSelectorto iterative loop (eliminates stack overflow risk)
Robustness
- Added
ColSpan/RowSpanclamping tomax(v, 1) CleanFileNamenow strips NUL bytesStoreCopytemp directories are now cleaned up on all pathstruncateTextnow slices by runes, not bytes — no more split UTF-8- Zip writer close error in
kfxdumpis now captured - Added 2-minute timeout on MHL child process via
exec.CommandContext - Child process stderr is now forwarded to
os.Stderr binary.Writein JPEG header rewrite replaced with directbinary.BigEndian.PutUint16into fixed array- Iterator
yieldreturn values are now checked at all call sites
Maintenance
- Extracted 8 default vignette SVGs and 2 placeholder SVGs to
//go:embedfiles - Added
//go:build windowsconstraint to MHL connector - Fixed YAML config tag typo:
jpeq_quality_level→jpeg_quality_level(breaking — existing config files need updating) - Fixed typos: "unnesessary", "deffered", "exits"→"exists", "wich"→"which", and others
- Removed dead
imageChangedflag for SVG path - Updated
Sentencesiterator doc to reflect actual behavior - Updated
docs/guide.mdanddocs/stylesheets.mdfor CSS security changes and config rename
Full Changelog: v1.0.0...v1.1.0
v1.0.0
Making an "official" release
Full Changelog: v0.0.27...v1.0.0