mirror of
https://github.com/gotenberg/gotenberg.git
synced 2026-08-10 09:32:13 +01:00
353 lines
13 KiB
Go
353 lines
13 KiB
Go
package gotenberg
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"fmt"
|
|
"log/slog"
|
|
)
|
|
|
|
var (
|
|
// ErrPdfEngineMethodNotSupported is returned when a specific method of the
|
|
// PdfEngine interface is not supported by its current implementation.
|
|
ErrPdfEngineMethodNotSupported = errors.New("method not supported")
|
|
|
|
// ErrPdfSplitModeNotSupported is returned when the Split method of the
|
|
// PdfEngine interface does not support a requested PDF split mode.
|
|
ErrPdfSplitModeNotSupported = errors.New("split mode not supported")
|
|
|
|
// ErrPdfFormatNotSupported is returned when the Convert method of the
|
|
// PdfEngine interface does not support a requested PDF format conversion.
|
|
ErrPdfFormatNotSupported = errors.New("PDF format not supported")
|
|
|
|
// ErrPdfEngineMetadataValueNotSupported is returned when a metadata value
|
|
// is not supported.
|
|
ErrPdfEngineMetadataValueNotSupported = errors.New("metadata value not supported")
|
|
|
|
// ErrPdfEncryptionNotSupported is returned when encryption
|
|
// is not supported by the PDF engine.
|
|
ErrPdfEncryptionNotSupported = errors.New("encryption not supported")
|
|
|
|
// ErrPdfStampSourceNotSupported is returned when a stamp source type
|
|
// is not supported by the PDF engine.
|
|
ErrPdfStampSourceNotSupported = errors.New("stamp source not supported")
|
|
|
|
// ErrPdfRotateAngleNotSupported is returned when the rotation angle is
|
|
// not supported.
|
|
ErrPdfRotateAngleNotSupported = errors.New("rotation angle not supported")
|
|
|
|
// ErrPdfFacturXValueNotSupported is returned when a Factur-X field value
|
|
// (e.g., an unknown conformance level or document type) is not supported.
|
|
ErrPdfFacturXValueNotSupported = errors.New("Factur-X value not supported")
|
|
)
|
|
|
|
// PdfEngineInvalidArgsError represents an error returned by a PDF engine when
|
|
// invalid arguments are provided. It includes the name of the engine and a
|
|
// detailed message describing the issue.
|
|
type PdfEngineInvalidArgsError struct {
|
|
engine string
|
|
msg string
|
|
}
|
|
|
|
// Error implements the error interface.
|
|
func (e *PdfEngineInvalidArgsError) Error() string {
|
|
return fmt.Sprintf("%s: %s", e.engine, e.msg)
|
|
}
|
|
|
|
// NewPdfEngineInvalidArgs creates a new PdfEngineInvalidArgsError with the
|
|
// given engine name and message.
|
|
func NewPdfEngineInvalidArgs(engine, msg string) error {
|
|
return &PdfEngineInvalidArgsError{engine, msg}
|
|
}
|
|
|
|
const (
|
|
// StampSourceText represents a text-based stamp source.
|
|
StampSourceText string = "text"
|
|
|
|
// StampSourceImage represents an image-based stamp source.
|
|
StampSourceImage string = "image"
|
|
|
|
// StampSourcePDF represents a PDF-based stamp source.
|
|
StampSourcePDF string = "pdf"
|
|
)
|
|
|
|
// Stamp gathers the data required to apply a watermark or stamp to a PDF.
|
|
type Stamp struct {
|
|
// Source is one of "text", "image", or "pdf".
|
|
Source string
|
|
|
|
// Expression is the text content (for text source) or file path (for
|
|
// image/pdf source).
|
|
Expression string
|
|
|
|
// Pages is the optional page range to apply the stamp to.
|
|
Pages string
|
|
|
|
// Options holds engine-specific styling options.
|
|
Options map[string]string
|
|
}
|
|
|
|
const (
|
|
// SplitModeIntervals represents a mode where a PDF is split at specific
|
|
// intervals.
|
|
SplitModeIntervals string = "intervals"
|
|
|
|
// SplitModePages represents a mode where a PDF is split at specific page
|
|
// ranges.
|
|
SplitModePages string = "pages"
|
|
)
|
|
|
|
// SplitMode gathers the data required to split a PDF into multiple parts.
|
|
type SplitMode struct {
|
|
// Mode is either "intervals" or "pages".
|
|
Mode string
|
|
|
|
// Span is either the intervals or the page ranges to extract, depending on
|
|
// the selected mode.
|
|
Span string
|
|
|
|
// Unify specifies whether to put extracted pages into a single file or as
|
|
// many files as there are page ranges. Only works with "pages" mode.
|
|
Unify bool
|
|
}
|
|
|
|
const (
|
|
// PdfA1a represents the PDF/A-1a format.
|
|
PdfA1a string = "PDF/A-1a"
|
|
|
|
// PdfA1b represents the PDF/A-1b format.
|
|
PdfA1b string = "PDF/A-1b"
|
|
|
|
// PdfA2a represents the PDF/A-2a format.
|
|
PdfA2a string = "PDF/A-2a"
|
|
|
|
// PdfA2b represents the PDF/A-2b format.
|
|
PdfA2b string = "PDF/A-2b"
|
|
|
|
// PdfA2u represents the PDF/A-2u format.
|
|
PdfA2u string = "PDF/A-2u"
|
|
|
|
// PdfA3a represents the PDF/A-3a format.
|
|
PdfA3a string = "PDF/A-3a"
|
|
|
|
// PdfA3b represents the PDF/A-3b format.
|
|
PdfA3b string = "PDF/A-3b"
|
|
|
|
// PdfA3u represents the PDF/A-3u format.
|
|
PdfA3u string = "PDF/A-3u"
|
|
)
|
|
|
|
// PdfFormats specifies the target formats for a PDF conversion.
|
|
type PdfFormats struct {
|
|
// PdfA denotes the PDF/A standard format (e.g., PDF/A-1a).
|
|
PdfA string
|
|
|
|
// PdfUa indicates whether the PDF should comply
|
|
// with the PDF/UA (Universal Accessibility) standard.
|
|
PdfUa bool
|
|
}
|
|
|
|
// PdfPermissions gathers the document permissions enforced when a PDF is
|
|
// encrypted. Each field defaults to true (the action is allowed); set a field
|
|
// to false to restrict it. Restrictions are advisory: viewers honor them, but
|
|
// they are not cryptographically enforced once the document opens.
|
|
type PdfPermissions struct {
|
|
// AllowPrinting permits printing the document.
|
|
AllowPrinting bool
|
|
|
|
// AllowCopying permits extracting text and graphics.
|
|
AllowCopying bool
|
|
|
|
// AllowModifying permits changing the document content.
|
|
AllowModifying bool
|
|
|
|
// AllowAnnotating permits adding or modifying annotations.
|
|
AllowAnnotating bool
|
|
|
|
// AllowFillingForms permits filling in form fields.
|
|
AllowFillingForms bool
|
|
|
|
// AllowAssembling permits inserting, deleting, and rotating pages.
|
|
AllowAssembling bool
|
|
}
|
|
|
|
// Restricted reports whether at least one permission is denied.
|
|
func (p PdfPermissions) Restricted() bool {
|
|
return !p.AllowPrinting ||
|
|
!p.AllowCopying ||
|
|
!p.AllowModifying ||
|
|
!p.AllowAnnotating ||
|
|
!p.AllowFillingForms ||
|
|
!p.AllowAssembling
|
|
}
|
|
|
|
// EncryptOptions gathers the parameters for encrypting a PDF. An empty
|
|
// UserPassword with a set OwnerPassword produces an owner-only document: it
|
|
// opens without a password but enforces the [PdfPermissions].
|
|
type EncryptOptions struct {
|
|
// UserPassword is required to open the document. Empty means no open
|
|
// password.
|
|
UserPassword string
|
|
|
|
// OwnerPassword grants full access (lifts the permission restrictions).
|
|
// When empty, it defaults to UserPassword.
|
|
OwnerPassword string
|
|
|
|
// Permissions are the actions allowed when opened with the user password.
|
|
Permissions PdfPermissions
|
|
}
|
|
|
|
// Bookmark represents a node in the PDF document's outline
|
|
// (table of contents).
|
|
type Bookmark struct {
|
|
Title string `json:"title"`
|
|
Page int `json:"page"`
|
|
Children []Bookmark `json:"children,omitempty"`
|
|
}
|
|
|
|
const (
|
|
// FacturXConformanceMinimum represents the MINIMUM Factur-X conformance level.
|
|
FacturXConformanceMinimum string = "MINIMUM"
|
|
|
|
// FacturXConformanceBasicWL represents the BASIC WL Factur-X conformance level.
|
|
FacturXConformanceBasicWL string = "BASIC WL"
|
|
|
|
// FacturXConformanceBasic represents the BASIC Factur-X conformance level.
|
|
FacturXConformanceBasic string = "BASIC"
|
|
|
|
// FacturXConformanceEN16931 represents the EN 16931 Factur-X conformance level.
|
|
FacturXConformanceEN16931 string = "EN 16931"
|
|
|
|
// FacturXConformanceExtended represents the EXTENDED Factur-X conformance level.
|
|
FacturXConformanceExtended string = "EXTENDED"
|
|
|
|
// FacturXConformanceXRechnung represents the XRECHNUNG Factur-X conformance level.
|
|
FacturXConformanceXRechnung string = "XRECHNUNG"
|
|
|
|
// FacturXDocumentTypeInvoice represents the INVOICE Factur-X document type.
|
|
FacturXDocumentTypeInvoice string = "INVOICE"
|
|
|
|
// FacturXDocumentTypeOrder represents the ORDER Factur-X document type.
|
|
FacturXDocumentTypeOrder string = "ORDER"
|
|
|
|
// FacturXDocumentTypeOrderResponse represents the ORDER_RESPONSE Factur-X document type.
|
|
FacturXDocumentTypeOrderResponse string = "ORDER_RESPONSE"
|
|
|
|
// FacturXDocumentTypeOrderChange represents the ORDER_CHANGE Factur-X document type.
|
|
FacturXDocumentTypeOrderChange string = "ORDER_CHANGE"
|
|
|
|
// FacturXDocumentFileName is the canonical name of the embedded XML invoice
|
|
// mandated by the Factur-X standard. Validators expect this exact name.
|
|
FacturXDocumentFileName string = "factur-x.xml"
|
|
)
|
|
|
|
// FacturX gathers the properties required by the Factur-X/ZUGFeRD standard for
|
|
// the document-level XMP metadata packet of a PDF/A-3.
|
|
type FacturX struct {
|
|
// ConformanceLevel is one of the FacturXConformance* values.
|
|
ConformanceLevel string
|
|
|
|
// DocumentType is one of the FacturXDocumentType* values.
|
|
DocumentType string
|
|
|
|
// DocumentFileName is the name of the embedded XML invoice. It is set
|
|
// internally to the canonical [FacturXDocumentFileName], not by the caller.
|
|
DocumentFileName string
|
|
|
|
// Version is the Factur-X version (e.g., "1.0").
|
|
Version string
|
|
}
|
|
|
|
// PdfEngine provides an interface for operations on PDFs. Implementations
|
|
// can use various tools like PDFtk, or implement functionality directly in
|
|
// Go.
|
|
//
|
|
//nolint:dupl
|
|
type PdfEngine interface {
|
|
// Merge combines multiple PDFs into a single PDF. The resulting page order
|
|
// is determined by the order of files provided in inputPaths.
|
|
Merge(ctx context.Context, logger *slog.Logger, inputPaths []string, outputPath string) error
|
|
|
|
// Split splits a given PDF file.
|
|
Split(ctx context.Context, logger *slog.Logger, mode SplitMode, inputPath, outputDirPath string) ([]string, error)
|
|
|
|
// Flatten merges existing annotation appearances with page content,
|
|
// effectively deleting the original annotations. This process can flatten
|
|
// forms as well as forms share a relationship with annotations. Note that
|
|
// this operation is irreversible.
|
|
Flatten(ctx context.Context, logger *slog.Logger, inputPath string) error
|
|
|
|
// Convert transforms a given PDF to the specified formats defined in
|
|
// PdfFormats. If no format, it does nothing.
|
|
Convert(ctx context.Context, logger *slog.Logger, formats PdfFormats, inputPath, outputPath string) error
|
|
|
|
// ReadMetadata extracts the metadata of a given PDF file.
|
|
ReadMetadata(ctx context.Context, logger *slog.Logger, inputPath string) (map[string]any, error)
|
|
|
|
// PageCount returns the number of pages in a PDF file.
|
|
PageCount(ctx context.Context, logger *slog.Logger, inputPath string) (int, error)
|
|
|
|
// WriteMetadata writes the metadata into a given PDF file.
|
|
WriteMetadata(ctx context.Context, logger *slog.Logger, metadata map[string]any, inputPath string) error
|
|
|
|
// ReadBookmarks reads the document outline (bookmarks) of a PDF file.
|
|
ReadBookmarks(ctx context.Context, logger *slog.Logger, inputPath string) ([]Bookmark, error)
|
|
|
|
// WriteBookmarks adds a document outline (bookmarks) to a PDF file.
|
|
// The bookmarks parameter represents the hierarchical tree of the outline.
|
|
WriteBookmarks(ctx context.Context, logger *slog.Logger, inputPath string, bookmarks []Bookmark) error
|
|
|
|
// Encrypt adds password protection and permission restrictions to a PDF
|
|
// file, as described by [EncryptOptions]. An empty user password with a set
|
|
// owner password yields an owner-only document (opens without a password,
|
|
// permissions enforced).
|
|
Encrypt(ctx context.Context, logger *slog.Logger, inputPath string, opts EncryptOptions) error
|
|
|
|
// EmbedFiles embeds files into a PDF. All files are embedded as file attachments
|
|
// without modifying the main PDF content.
|
|
// TODO: attachments instead? Rename the route?
|
|
EmbedFiles(ctx context.Context, logger *slog.Logger, filePaths []string, inputPath string) error
|
|
|
|
// EmbedFilesMetadata sets metadata (such as MIME type and AFRelationship)
|
|
// on already-embedded files in a PDF. The metadata map is keyed by
|
|
// filename, with each value being a map of property names to values
|
|
// (e.g., "mimeType" and "relationship").
|
|
EmbedFilesMetadata(ctx context.Context, logger *slog.Logger, metadata map[string]map[string]string, inputPath string) error
|
|
|
|
// Watermark applies a watermark (behind page content) to a PDF file.
|
|
Watermark(ctx context.Context, logger *slog.Logger, inputPath string, stamp Stamp) error
|
|
|
|
// Stamp applies a stamp (on top of page content) to a PDF file.
|
|
Stamp(ctx context.Context, logger *slog.Logger, inputPath string, stamp Stamp) error
|
|
|
|
// Rotate rotates pages of a PDF file by the given angle (90, 180, 270).
|
|
// If pages is empty, all pages are rotated.
|
|
Rotate(ctx context.Context, logger *slog.Logger, inputPath string, angle int, pages string) error
|
|
|
|
// InjectFacturXXMP injects Factur-X/ZUGFeRD XMP metadata into the
|
|
// document-level XMP packet (Catalog /Metadata stream) of a PDF/A-3. It
|
|
// registers the fx namespace, the four fx properties, and the matching
|
|
// PDF/A extension schema so the result stays PDF/A-valid.
|
|
InjectFacturXXMP(ctx context.Context, logger *slog.Logger, facturX FacturX, inputPath string) error
|
|
|
|
// ReadPdfAConformance reads the PDF/A part and conformance (e.g., "3" and
|
|
// "B") from the document-level XMP packet (Catalog /Metadata stream,
|
|
// pdfaid:part and pdfaid:conformance). It returns empty strings when the
|
|
// document carries no PDF/A identification.
|
|
ReadPdfAConformance(ctx context.Context, logger *slog.Logger, inputPath string) (part string, conformance string, err error)
|
|
}
|
|
|
|
// PdfEngineProvider offers an interface to instantiate a [PdfEngine].
|
|
// This is used to decouple the creation of a [PdfEngine] from its consumers.
|
|
//
|
|
// Example:
|
|
//
|
|
// func (m *YourModule) Provision(ctx *gotenberg.Context) error {
|
|
// provider, _ := ctx.Module(new(gotenberg.PdfEngineProvider))
|
|
// engine, _ := provider.(gotenberg.PdfEngineProvider).PdfEngine()
|
|
// }
|
|
type PdfEngineProvider interface {
|
|
// PdfEngine returns an instance of the [PdfEngine] interface for PDF operations.
|
|
PdfEngine() (PdfEngine, error)
|
|
}
|