Skip to content

Releases: rupor-github/fb2cng

v1.1.8

06 Mar 16:49
1eaed8d

Choose a tag to compare

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

01 Mar 19:53
eaf445b

Choose a tag to compare

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

24 Feb 15:33
2ac8d97

Choose a tag to compare

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

23 Feb 13:08
ec98446

Choose a tag to compare

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

22 Feb 17:20
b0eb44f

Choose a tag to compare

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

22 Feb 15:46
2ba99aa

Choose a tag to compare

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.pidMapWithOffset format 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

21 Feb 22:10
f355183

Choose a tag to compare

Bug fixes

  • Removed hardcoded registration of footnote>p descendant selector that unconditionally overrode user CSS. Footnote paragraph styling is now handled entirely through the CSS cascade.
  • Fixed missing position:footer / yj.classification:footnote markers 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

17 Feb 23:33
22c1e13

Choose a tag to compare

Maintenance release - use latest gencfg package.
No functional changes

Full Changelog: v1.1.0...v1.1.1

v1.1.0

15 Feb 20:18
d842fd9

Choose a tag to compare

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.Lowercase in concurrent transliteration calls

High

  • SecretString no longer leaks secrets via fmt.Sprintf / %v — added String() and GoString() methods
  • CSS url() resolution now uses os.DirFS to 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 matches allSubstringsAndValues() behavior
  • Fixed CSS injection — selector and url() values are now properly escaped
  • Fixed parseDimension — rewritten to correctly reject malformed CSS dimensions
  • Eliminated stale Imports/FontFaces sync bug by replacing fields with methods
  • Removed dead code in indexHref — replaced url.Parse() with explicit scheme allowlist
  • encodeImage now returns an error for unsupported formats instead of silent nil, nil
  • Fixed Report.Close() — both arc.Close() and r.file.Close() errors are now reported via errors.Join
  • Fixed %v%w in error wrapping in config.Dump()
  • Fixed case-sensitivity mismatch in MHL connector — target is now normalized to lowercase
  • Fixed isTitleEmpty — now recurses into child segments via AsPlainText()

Performance

  • Replaced += string concatenation with strings.Builder in hot hyphenation loops
  • Cached HTML entities JSON parsing with sync.Once — no longer re-parsed on every Prepare()
  • Moved isKnownTextTag map to package level — no longer allocated per call
  • Fixed O(n²) AsTOCText — tracks lastByte instead of calling buf.String() in loop
  • Replaced strings.NewReader(string(bytes)) with bytes.NewReader to avoid copy
  • Converted recursive parseDescendantSelector to iterative loop (eliminates stack overflow risk)

Robustness

  • Added ColSpan/RowSpan clamping to max(v, 1)
  • CleanFileName now strips NUL bytes
  • StoreCopy temp directories are now cleaned up on all paths
  • truncateText now slices by runes, not bytes — no more split UTF-8
  • Zip writer close error in kfxdump is now captured
  • Added 2-minute timeout on MHL child process via exec.CommandContext
  • Child process stderr is now forwarded to os.Stderr
  • binary.Write in JPEG header rewrite replaced with direct binary.BigEndian.PutUint16 into fixed array
  • Iterator yield return values are now checked at all call sites

Maintenance

  • Extracted 8 default vignette SVGs and 2 placeholder SVGs to //go:embed files
  • Added //go:build windows constraint to MHL connector
  • Fixed YAML config tag typo: jpeq_quality_leveljpeg_quality_level (breaking — existing config files need updating)
  • Fixed typos: "unnesessary", "deffered", "exits"→"exists", "wich"→"which", and others
  • Removed dead imageChanged flag for SVG path
  • Updated Sentences iterator doc to reflect actual behavior
  • Updated docs/guide.md and docs/stylesheets.md for CSS security changes and config rename

Full Changelog: v1.0.0...v1.1.0

v1.0.0

13 Feb 16:56
7f251ad

Choose a tag to compare

Making an "official" release

Full Changelog: v0.0.27...v1.0.0