folio

repository·main·Indexed 21 days ago

https://github.com/carlos7ags/folio

A comprehensive PDF library for Go featuring a high-level layout engine, in-process HTML-to-PDF conversion with CSS Flexbox and Grid support, and advanced capabilities including digital signatures (PAdES), redaction, and internationalization for RTL, Indic, and CJK scripts. It provides tools for PDF/A and PDF/UA compliance, AcroForm generation, barcode creation, and PDF manipulation such as merging and text extraction.

Tokens
21.7K
Snippets
55
Records
93
Agent score
71%

What's inside folio

  1. Understand Folio's CSS support and parsing behavior

    main

    Folio's HTML-to-PDF converter supports a subset of 139 CSS properties.

    Key behaviors:

    • Silent Failure: Properties not explicitly listed in the documentation are silently ignored during rendering. There are no warnings for unknown properties.
    • Asset Escalation: While unknown CSS properties are always silent, you can use html.Options.StrictAssets to escalate certain other asset failures.
    • Mathematical Functions: calc(), min(), max(), and clamp() are supported wherever <length> or <percentage> values are accepted.
    • Color Support: Folio renders in sRGB only. While it supports named colors, hex, rgb(), rgba(), hsl(), hsla(), and cmyk(), it does not support oklch() or color-mix().
  2. Explore Folio capabilities via examples

    main

    The examples/ directory contains demonstrations of various Folio features. You can explore these subdirectories to see implementation patterns for:

    • Typography & Scripts: RTL (Arabic, Hebrew), Indic (Devanagari), and CJK (Chinese, Japanese, Korean) with font subsetting.
    • Layout & Content: HTML to PDF (flexbox, tables, page breaks), multi-page reports, and table cell spanning (table-rowspan).
    • Advanced PDF Features: Interactive AcroForm fields (forms), hyperlinks and bookmarks (links), and digital signatures (sign).
    • Data & Compliance: Barcodes (QR Code, Code 128, EAN-13), PDF/A-3B invoices with XML attachments (zugferd), and redaction of sensitive text (redact).
    • PDF Manipulation: Loading existing PDFs as templates (import-page), and merging or extracting text from PDFs (merge).
  3. Identify Folio non-goals and limitations

    main

    To avoid attempting unsupported tasks, be aware that Folio does not provide:

    • PDF Rendering/Rasterization: It creates and reads PDFs but does not render them to pixels (use mupdf or poppler for this).
    • JavaScript/Actions: No support for embedded PDF JavaScript.
    • Multimedia Annotations: No support for sound, video, 3D, or rich media.
    • XFA Forms: Supports AcroForms only.
    • Full CSS Compliance: The HTML converter supports only a practical subset of CSS.
    • Image Manipulation: No resizing, cropping, or format transcoding.
    • Certificate/Key Management: The sign package accepts keys/certificates but does not manage or store them.
  4. Explore Folio package structure

    main

    Folio is organized into specialized packages for different PDF generation and manipulation tasks:

    • core: PDF object model
    • content: Content stream builder
    • document: High-level Document API (pages, outlines, PDF/A, watermarks, page import, WriteOptions)
    • font: Font embedding (Standard 14, TrueType/OpenType), subsetting, GSUB, GPOS
    • image: Support for JPEG, PNG, TIFF, WebP, GIF
    • layout: Layout engine (elements, rendering, bidi, Arabic/Devanagari shaping, CJK)
    • barcode: Code128, QR, EAN-13
    • forms: AcroForms (text, checkbox, radio, dropdown, signature)
    • html: HTML + CSS to PDF conversion
    • svg: SVG to PDF rendering
    • sign: Digital signatures (PAdES, CMS, timestamps)
    • reader: PDF parser, text extraction, merge, redaction, page import
    • tmpl: html/template integration
    • unicode/grapheme: UAX #29 grapheme clusters
    • export: C shared library (372 exported functions)
    • cmd/folio: CLI tool
  5. Understand the Folio package architecture and responsibilities

    main

    Folio is organized into specialized packages, each owning a single concern. Understanding these boundaries helps you choose the correct package for your task:

    • document: Top-level assembly (pages, fonts, images, metadata, PDF/A).
    • html: Converts HTML+CSS to layout.Element.
    • layout: Handles the element model, box layout, pagination, and rendering to content streams.
    • sign: Manages PAdES digital signatures, CMS, and TSA.
    • svg: Parses and renders SVG to content stream operators.
    • font: Manages font loading, parsing, metrics, and embedding.
    • image: Decodes JPEG/PNG/TIFF and constructs PDF XObjects.
    • barcode: Generates barcodes (QR, Code 128, EAN-13).
    • content: Builds content streams (operators to bytes).
    • forms: Creates and fills AcroForm fields.
    • reader: Parses PDFs, resolves objects, extracts text, and merges pages.
    • core: Low-level PDF object types, serialization, and encryption.
    • export: Provides a C ABI for FFI consumers.
    • barcode: Generates barcodes (QR, Code 128, EAN-13).
    • svg: Parses and renders SVG to content stream operators.
    • document: Top-level document assembly: pages, fonts, images, outlines, metadata, PDF/A, tagged PDF.
    • export: C ABI for FFI consumers.
    • cmd/folio: CLI tool for merge, info, text extraction, and signing.
    • cmd/wasm: WebAssembly entry point for browser use.
    • cmd/gen-metrics: Build-time code generator for AFM files.
  6. Understand the Folio layout and rendering architecture

    main

    Folio follows a deterministic, non-mutating layout model. The core workflow is:

    1. Layout Planning: Element.PlanLayout(area) produces an immutable LayoutPlan.
    2. Rendering: PlacedBlock.Draw(ctx, x, y) generates the necessary PDF operators.

    Key architectural features:

    • No mutation: Elements can be laid out multiple times safely.
    • Content splitting: Supports splitting content across pages via overflow elements.
    • Intrinsic sizing: Supports MinWidth/MaxWidth for automatic column sizing in tables.
    • Deterministic output: Ensures byte-for-byte reproducible PDFs.
    • Dependencies: Relies on golang.org/x/image, golang.org/x/net, and golang.org/x/text.
  7. Understand Folio's versioning and API stability

    main

    Folio follows semantic versioning (SemVer).

    Current Status: The project is currently in the v0.x phase.

    Important for Developers:

    • Breaking Changes: Because the project is pre-v1.0, breaking API changes may occur during minor releases.
    • Stability Goal: The project aims to reach v1.0 with a stable public API.
    • Deprecation Policy: When possible, deprecated symbols are maintained for at least one minor release to allow for migration.
  8. Handle errors and concurrency in Folio

    main

    Error Handling

    Public API functions return error. Errors are wrapped using fmt.Errorf("package: context: %w", err) to allow for inspection via errors.Is and errors.Unwrap.

    • Sentinel Errors: Used sparingly for branching logic (e.g., reader.ErrMemoryLimitExceeded).
    • Panics: Reserved strictly for programming errors (e.g., passing nil where non-nil is required). They are never used for malformed input.

    Concurrency

    • Non-thread-safe: Individual Folio objects (documents, readers, layout elements) are not safe for concurrent use from multiple goroutines. You must synchronize access.
    • Thread-safe Layout: The layout phase produces immutable LayoutPlan values. This allows multiple elements to be laid out concurrently if you manage the goroutines.
    • Thread-safe Reader: The reader package is safe to use from multiple goroutines after the initial parsing (Open or Parse) has completed, as the parsed state is read-only.
  9. Handle monetary amounts with the Amount type

    main

    The zugferd package uses a specialized Amount type (an int64 representing minor units, e.g., cents) to ensure exact arithmetic and byte-stable XML output.

    Note: This implementation currently only supports two-decimal currencies (like EUR, USD, GBP). Three-decimal (BHD) and zero-decimal (JPY) currencies are not supported in this version.

    // Amount is a minor-units integer type
    type Amount int64
    
    // Usage patterns:
    // NewAmount(units, cents)
    // ParseAmount("401.63")
    // .String() renders fixed two-decimal form
    // .Add() for totals
  10. Internationalization and Script Shaping

    main

    Folio supports advanced text shaping for various script families:

    • LTR (Latin, Cyrillic, Greek): Standard glyph runs with GSUB ligatures and GPOS kerning.
    • RTL (Arabic, Hebrew, Farsi): Uses UAX #9 bidi and Arabic contextual shaping. Use dir="rtl" in HTML or CSS to set direction.
    • Indic (Devanagari): Five-phase OpenType pipeline (reordering, substitution, conjunct formation).
    • CJK (Japanese, Chinese, Korean): Embedded TrueType subset with JIS X 4051 line-breaking.
  11. Understand new path semantics and @font-face resolution (v0.8.0)

    main

    Version 0.8.0 introduced changes to how paths are resolved within documents:

    • Path Normalization: Paths are normalized to fs.FS conventions (forward slashes only, no leading /, no .. traversal). Invalid paths are rejected before opening.
    • Root-relative paths: A leading / in src or href is now treated as the web-style root of the BaseFS (similar to <base href="/">), rather than an absolute filesystem path.
    • @font-face resolution: @font-face URLs now resolve relative to the containing stylesheet's location within the BaseFS, matching browser behavior.
      • Example: A stylesheet at css/site.css with @font-face { src: url(../fonts/Inter.ttf); } resolves to fonts/Inter.ttf from the BaseFS root.
      • Workaround: If you require root-anchored behavior, use a root-relative path (e.g., url(/fonts/Inter.ttf)) or move the rule into an inline <style> block.
  12. Note on re-encrypting modified documents

    main

    When you read an encrypted PDF, the document is fully decrypted in memory. If you modify this document and save it, the output is unencrypted by default.

    Folio does not automatically carry over the original /Encrypt configuration to the new file. To protect the output file, you must explicitly call document.SetEncryption on the write side before saving.